home *** CD-ROM | disk | FTP | other *** search
/ Sprite 1984 - 1993 / Sprite 1984 - 1993.iso / src / machserver / 1.098 / fs / fsStubs.c < prev    next >
C/C++ Source or Header  |  1991-08-08  |  107KB  |  4,205 lines

  1. /* 
  2.  * fsStubs.c --
  3.  *
  4.  *    Stubs for Unix compatible system calls.
  5.  *
  6.  * Copyright 1990 Regents of the University of California
  7.  * Permission to use, copy, modify, and distribute this
  8.  * software and its documentation for any purpose and without
  9.  * fee is hereby granted, provided that the above copyright
  10.  * notice appear in all copies.  The University of California
  11.  * makes no representations about the suitability of this
  12.  * software for any purpose.  It is provided "as is" without
  13.  * express or implied warranty.
  14.  */
  15.  
  16. #ifndef lint
  17. static char rcsid[] = "$Header: /sprite/src/kernel/fs/RCS/fsStubs.c,v 1.8 91/08/08 11:52:09 shirriff Exp $";
  18. #endif /* not lint */
  19.  
  20. #define MACH_UNIX_COMPAT
  21.  
  22. #include <sprite.h>
  23. #include <stdio.h>
  24. #include <stdlib.h>
  25. #include <string.h>
  26. #include <status.h>
  27. #include <errno.h>
  28. #include <assert.h>
  29. #include <fsprefix.h>
  30. #include <user/sys/types.h>
  31. #include <user/sys/file.h>
  32. #include <user/sys/wait.h>
  33. #include <user/sys/time.h>
  34. #include <user/sys/resource.h>
  35. #include <user/sys/stat.h>
  36. #include <user/sys/uio.h>
  37. #include <user/sys/ioctl.h>
  38. #include <user/sys/termio.h>
  39. #include <user/sys/termios.h>
  40. #include <user/sys/dir.h>
  41. #include <user/sys/dirent.h>
  42. #include <user/dev/tty.h>
  43. #include <user/dev/net.h>
  44. #include <user/dev/graphics.h>
  45. #include <user/bit.h>
  46. #include <user/fcntl.h>
  47. #include <mach.h>
  48. #include <proc.h>
  49. #include <vm.h>
  50. #include <fs.h>
  51. #include <fsUnixStubs.h>
  52. #include <procUnixStubs.h>
  53. #include <fsutil.h>
  54. #include <fsutilTrace.h>
  55. #include <fsio.h>
  56. #include <fslcl.h>
  57. #include <user/inet.h>
  58.  
  59. static char *errs[] = {"ENOERR", "EPERM", "ENOENT", "ESRCH", "EINTR", "EIO",
  60.     "ENXIO", "E2BIG", "ENOEXEC", "EBADF", "ECHILD", "EAGAIN", "ENOMEM",
  61.     "EACCES", "EFAULT", "ENOTBLK", "EBUSY", "EEXIST", "EXDEV", "ENODEV",
  62.     "ENOTDIR", "EISDIR", "EINVAL", "ENFILE", "EMFILE", "ENOTTY",
  63.     "ETXTBSY", "EFBIG", "ENOSPC", "ESPIPE", "EROFS", "EMLINK", "EPIPE",
  64.     "EDOM", "ERANGE", "EWOULDBLOCK", "EINPROGRESS", "EALREADY", "ENOTSOCK",
  65.     "EDESTADDRREQ", "EMSGSIZE", "EPROTOTYPE", "ENOPROTOOPT",
  66.     "EPROTONOSUPPORT", "ESOCKTNOSUPPORT", "EOPNOTSUPP", "EPFNOSUPPORT",
  67.     "EAFNOSUPPORT", "EADDRINUSE", "EADDRNOTAVAIL", "ENETDOWN",
  68.     "ENETUNREACH", "ENETRESET", "ECONNABORTED", "ECONNRESET", "ENOBUFS",
  69.     "EISCONN", "ENOTCONN", "ESHUTDOWN", "ETIMEDOUT", "ECONNREFUSED",
  70.     "ELOOP", "ENAMETOOLONG", "EHOSTDOWN", "EHOSTUNREACH", "ENOTEMPTY",
  71.     "EPROCLIM", "EUSERS", "EDQUOT", "ESTALE", "EREMOTE"};
  72.  
  73. #undef Mach_SetErrno
  74. #define Mach_SetErrno(err) if (debugFsStubs) \
  75.     printf("Error %d (%s) at %d in %s\n", err,\
  76.     err<sizeof(errs)/sizeof(char *)?errs[err]:"",\
  77.     __LINE__, __FILE__); Proc_GetActualProc()->unixErrno = (err)
  78.  
  79. /*
  80.  * The following defines are flags that are defined differently in
  81.  * termios.h (T_) and ioctl.h (I_).
  82.  * We define them uniquely here, so we don't get messed up.
  83.  */
  84. #define T_NL1    0x00000100
  85. #define I_NL1    0x00000100
  86. #define I_NL2    0x00000200
  87. #define I_CR0    0x00000000
  88. #define T_CR1    0x00000200
  89. #define I_CR1    0x00001000
  90. #define T_CR2    0x00000400
  91. #define I_CR2    0x00002000
  92. #define T_CR3    0x00000600
  93. #define I_CR3    0x00003000
  94. #define T_TAB1    0x00000800
  95. #define I_TAB1    0x00000400
  96. #define T_TAB2    0x00001000
  97. #define I_TAB2    0x00000800
  98. #define T_NOFLSH    0x00000080
  99. #define I_NOFLSH    0x80000000
  100. #define T_TOSTOP    0x00000100
  101. #define I_TOSTOP    0x00400000
  102. #define T_FLUSHO    0x00002000
  103. #define I_FLUSHO    0x00800000
  104.  
  105. /*
  106.  * Select defines from mach/ds3100.md/socket.h
  107.  */
  108. #define MAX_NUM_STREAMS        1024
  109. #define BITS_PER_ROW        32
  110. #define MAX_NUM_ROWS        (MAX_NUM_STREAMS/BITS_PER_ROW)
  111.  
  112. #ifndef Mach_SetErrno
  113. #define Mach_SetErrno(err)
  114. #endif
  115.  
  116. int debugFsStubs = 0;
  117.  
  118. static int CvtSpriteToUnixType _ARGS_((register int spriteFileType));
  119. static void CvtSpriteToUnixAtts _ARGS_((register Fs_Attributes *spriteAttsPtr,
  120.     register struct stat *unixAttsPtr));
  121. static void CvtTermiosToSgttyb _ARGS_((int termiosFlag, struct termios *ts,
  122.     struct sgttyb *ttyb, unsigned int *lmode, struct tchars *tc,
  123.     struct ltchars *ltc));
  124. static void CvtSgttybToTermios _ARGS_((struct sgttyb *ttyb,
  125.     unsigned int *lmode, struct tchars *tc, struct ltchars *ltc,
  126.     struct termios *ts));
  127. static int GetTermInfo(Fs_Stream *streamPtr, Fs_IOCParam *ioctl,
  128.     struct sgttyb *ttyb, unsigned int *lmode, struct tchars *tc,
  129.     struct ltchars *ltc);
  130. extern int CheckIfPresent _ARGS_((char *name));
  131. static char *copyin _ARGS_((char *string));
  132. static int Fs_GetdirInt _ARGS_((int fd, int nbytes, Address buf, long *off));
  133.  
  134. /*
  135.  *----------------------------------------------------------------------
  136.  *
  137.  * CvtSpriteToUnixType --
  138.  *
  139.  *    Convert from Sprite file types to the IFMT mode bits of a unix file
  140.  *
  141.  * Results:
  142.  *    Unix file type bits.
  143.  *
  144.  * Side effects:
  145.  *     none.
  146.  *
  147.  *----------------------------------------------------------------------
  148.  */
  149. static int
  150. CvtSpriteToUnixType(spriteFileType)
  151.     register    int spriteFileType;
  152. {
  153.     register unixModeBits;
  154.  
  155.     switch (spriteFileType) {
  156.     default:
  157.     case FS_FILE:
  158.         unixModeBits = S_IFREG;
  159.         break;
  160.     case FS_DIRECTORY:
  161.         unixModeBits = S_IFDIR;
  162.         break;
  163.     case FS_SYMBOLIC_LINK:
  164.         unixModeBits = S_IFLNK;
  165.         break;
  166.     case FS_DEVICE:
  167.     case FS_REMOTE_DEVICE:        /* not used */
  168.         unixModeBits = S_IFCHR;
  169.         break;
  170.     case FS_LOCAL_PIPE:        /* not used */
  171.     case FS_NAMED_PIPE:
  172.         unixModeBits = S_IFIFO;
  173.         break;
  174.     case FS_REMOTE_LINK:
  175.         unixModeBits = S_IFLNK;    /* a lie */
  176.         break;
  177.     case FS_PSEUDO_DEV:
  178.         unixModeBits = S_IFCHR;    /* another lie */
  179.         break;
  180.     }
  181.     return(unixModeBits);
  182. }
  183.  
  184. /*
  185.  *----------------------------------------------------------------------
  186.  *
  187.  * CvtSpriteToUnixAtts --
  188.  *
  189.  *    Procedure to convert the Sprite file system attributes 
  190.  *    structure to the Unix format.
  191.  *
  192.  * Results:
  193.  *    none.
  194.  *
  195.  * Side effects:
  196.  *     none.
  197.  *
  198.  *----------------------------------------------------------------------
  199.  */
  200. static void
  201. CvtSpriteToUnixAtts(spriteAttsPtr, unixAttsPtr)
  202.     register    struct stat    *unixAttsPtr;
  203.     register    Fs_Attributes    *spriteAttsPtr;
  204. {
  205.     unixAttsPtr->st_dev        = spriteAttsPtr->domain;
  206.     unixAttsPtr->st_ino        = spriteAttsPtr->fileNumber;
  207.     unixAttsPtr->st_mode    = (spriteAttsPtr->permissions & 0xfff) |
  208.                     CvtSpriteToUnixType(spriteAttsPtr->type);
  209.     unixAttsPtr->st_nlink    = spriteAttsPtr->numLinks;
  210.     unixAttsPtr->st_uid        = spriteAttsPtr->uid;
  211.     unixAttsPtr->st_gid        = spriteAttsPtr->gid;
  212.     unixAttsPtr->st_rdev    = (spriteAttsPtr->devType << 8) |
  213.                   (spriteAttsPtr->devUnit & 0xff);
  214.     unixAttsPtr->st_size    = spriteAttsPtr->size;
  215.     unixAttsPtr->st_blksize    = spriteAttsPtr->blockSize;
  216.     unixAttsPtr->st_blocks    = spriteAttsPtr->blocks * 2;
  217.     unixAttsPtr->st_atime    = spriteAttsPtr->accessTime.seconds;
  218.     unixAttsPtr->st_spare1    = 0;
  219.     unixAttsPtr->st_mtime    = spriteAttsPtr->dataModifyTime.seconds;
  220.     unixAttsPtr->st_spare2    = 0;
  221.     unixAttsPtr->st_ctime    = spriteAttsPtr->descModifyTime.seconds;
  222.     unixAttsPtr->st_spare3    = 0;
  223.     /*
  224.      * The Unix stat structure is 8 bytes shorter than we declare it in
  225.      * sys/stat.h.  The Unix stat structure has 2 unused words on the
  226.      * end.
  227.      */
  228.     unixAttsPtr->st_serverID    = 0;
  229.     unixAttsPtr->st_version    = 0;
  230.     /*
  231.     unixAttsPtr->st_serverID    = spriteAttsPtr->serverID;
  232.     unixAttsPtr->st_version    = spriteAttsPtr->version;
  233.     unixAttsPtr->st_userType    = spriteAttsPtr->userType;
  234.     unixAttsPtr->st_devServerID = spriteAttsPtr->devServerID;
  235.     */
  236.     return;
  237. }
  238.  
  239.  
  240. /*
  241.  *----------------------------------------------------------------------
  242.  *
  243.  * CvtTermiosToSgttyb --
  244.  *
  245.  *    Convert from termios structure to sgttyb structure.
  246.  *    Note: ttyb, lmode, tc, and ltc must be initialized on entry.
  247.  *    This routine is carefully set up to match the behavior
  248.  *    of SunOS for all input combinations.  As a result, this
  249.  *    routine is not intuitive.  It's probably best not to
  250.  *    change this routine unless you have a good reason.
  251.  *    Then again, there's a good chance I got something wrong.
  252.  *
  253.  * Results:
  254.  *    None.
  255.  *
  256.  * Side effects:
  257.  *    Changes ttyb, lmode, tc, ltc.
  258.  *
  259.  *----------------------------------------------------------------------
  260.  */
  261. static void
  262. CvtTermiosToSgttyb(termiosFlag, ts, ttyb, lmode, tc, ltc)
  263.     int termiosFlag;        /* 1 if termios, 0 if termio. */
  264.     struct termios *ts;        /* In */
  265.     struct sgttyb *ttyb;    /* In, out */
  266.     unsigned int *lmode;    /* In, out */
  267.     struct tchars *tc;        /* In, out */
  268.     struct ltchars *ltc;    /* In, out */
  269. {
  270.     unsigned int flag, iflag, oflag, lflag, cflag;
  271.  
  272.     iflag = ts->c_iflag;
  273.     oflag = ts->c_oflag;
  274.     lflag = ts->c_lflag;
  275.     cflag = ts->c_cflag;
  276.  
  277.     flag = EVENP|ODDP|CBREAK;
  278.  
  279.     if (!(cflag&PARENB)&&(cflag&CSIZE)==CS8) {
  280.     flag &= ~(ODDP|EVENP|PASS8);
  281.     flag |= ttyb->sg_flags & (ODDP|EVENP);
  282.     if (*lmode&(PASS8>>16)) flag |= PASS8;
  283.     if (!(oflag&OPOST)) flag |= LITOUT;
  284.     if (!(iflag&ISTRIP)&&(oflag&OPOST)) flag |= PASS8;
  285.     } else {
  286.     if (cflag&PARODD) flag &= ~EVENP;
  287.     if ((iflag&INPCK)&&!(cflag&PARODD)) flag &= ~ODDP;
  288.     }
  289.  
  290.     if (!(iflag&IXANY)) flag |= DECCTQ;
  291.     if (iflag&IXOFF) flag |= TANDEM;
  292.  
  293.  
  294.     if (oflag&OLCUC) flag |= LCASE;
  295.     if (oflag&ONLCR) {
  296.     flag |= CRMOD;
  297.     if ((oflag&CRDLY)==T_CR2) {
  298.         flag |= I_CR1;
  299.     } else if ((oflag&CRDLY)==T_CR3) {
  300.         flag |= I_CR2;
  301.     }
  302.     }
  303.     if (oflag&ONLRET) {
  304.     if ((oflag&NLDLY)==T_NL1) flag |= I_NL2;
  305.     if (!(oflag&ONLCR) && (oflag&T_CR1)) {
  306.         flag |= I_NL1;
  307.     }
  308.     }
  309.     if (oflag&T_TAB1) flag |= I_TAB1;
  310.     if (oflag&T_TAB2) flag |= I_TAB2;
  311.     if (oflag&BSDLY) flag |= BSDELAY;
  312.     if (oflag&FFDLY) flag |= VTDELAY;
  313.  
  314.     if (cflag&CLOCAL) flag |= NOHANG;
  315.  
  316.     if (lflag&ICANON) flag &= ~CBREAK;
  317.     if (lflag&ECHOE) flag |= CRTERA|CRTBS;
  318.     if (lflag&T_NOFLSH) flag |= I_NOFLSH;
  319.     if (lflag&T_TOSTOP) flag |= I_TOSTOP;
  320.     if (lflag&ECHOCTL) flag |= CTLECH;
  321.     if (lflag&ECHOPRT) flag |= PRTERA;
  322.     if (lflag&ECHOKE) flag |= CRTKIL;
  323.     if (lflag&ECHO) flag |= ECHO;
  324.     if (lflag&T_FLUSHO) flag |= I_FLUSHO;
  325.  
  326.     ttyb->sg_flags = flag&0xffff;
  327.     *lmode = flag>>16;
  328.     ttyb->sg_ispeed = cflag&CBAUD;
  329.     ttyb->sg_ospeed = cflag&CBAUD;
  330.     tc->t_intrc = ts->c_cc[VINTR];
  331.     tc->t_quitc = ts->c_cc[VQUIT];
  332.     ttyb->sg_erase = ts->c_cc[VERASE];
  333.     ttyb->sg_kill = ts->c_cc[VKILL];
  334.     tc->t_eofc = ts->c_cc[VEOF];
  335.     if (termiosFlag) {
  336.     tc->t_startc = ts->c_cc[VSTART];
  337.     tc->t_stopc = ts->c_cc[VSTOP];
  338.     ltc->t_suspc = ts->c_cc[VSUSP];
  339.         ltc->t_dsuspc = ts->c_cc[VDSUSP];
  340.     ltc->t_rprntc = ts->c_cc[VREPRINT];
  341.     ltc->t_flushc = ts->c_cc[VDISCARD];
  342.     ltc->t_werasc = ts->c_cc[VWERASE];
  343.     ltc->t_lnextc = ts->c_cc[VLNEXT];
  344.     }
  345. }
  346.  
  347. /*
  348.  *----------------------------------------------------------------------
  349.  *
  350.  * CvtSgttybToTermios --
  351.  *
  352.  *    Convert from termios structure to sgttyb structure.
  353.  *    Note: ttyb and lmode must be initialized on entry.
  354.  *
  355.  * Results:
  356.  *    Changes ts.
  357.  *
  358.  * Side effects:
  359.  *     
  360.  *
  361.  *----------------------------------------------------------------------
  362.  */
  363. static void
  364. CvtSgttybToTermios(ttyb, lmode, tc, ltc, ts)
  365.     struct sgttyb *ttyb;    /* IN */
  366.     unsigned int *lmode;    /* IN */
  367.     struct tchars *tc;        /* IN */
  368.     struct ltchars *ltc;    /* IN */
  369.     struct termios *ts;        /* OUT */
  370. {
  371.     unsigned int flag;
  372.     unsigned int iflag, oflag, cflag, lflag;
  373.  
  374.     flag = ttyb->sg_flags | (*lmode<<16);
  375.     iflag = IMAXBEL|IXON|ISTRIP|IGNPAR|BRKINT|IXANY;
  376.     oflag = ONLRET|OPOST;
  377.     cflag = CREAD|CS8|B9600;
  378.     lflag = ICANON|ISIG|IEXTEN|ECHOK;
  379.     if (flag&CBREAK) lflag &= ~ICANON;
  380.     if (flag&TANDEM) iflag |= IXOFF;
  381.     if (flag&LCASE) {
  382.     iflag |= IUCLC;
  383.     oflag |= OLCUC;
  384.     lflag |= XCASE;
  385.     }
  386.     if (flag&ECHO) lflag |= ECHO;
  387.     if (flag&EVENP) {
  388.     iflag |= INPCK;
  389.     cflag |= PARENB;
  390.     cflag &= ~CS6;
  391.     if (flag&ODDP) {
  392.         iflag &= ~INPCK;
  393.     }
  394.     } else if (flag&ODDP) {
  395.     iflag |= INPCK;
  396.     cflag |= PARODD|PARENB;
  397.     cflag &= ~CS6;
  398.     }
  399.     if ((flag&NLDELAY)==I_NL2) {
  400.     oflag |= T_NL1;
  401.     }
  402.     if (flag&CRMOD) {
  403.     iflag |= ICRNL;
  404.     oflag |= ONLCR;
  405.     oflag &= ~CRDLY;
  406.     } else {
  407.     oflag &= ~CRDLY;
  408.     }
  409.     if (flag&I_TAB1) oflag |= T_TAB1;
  410.     if (flag&I_TAB2) oflag |= T_TAB2;
  411.     if ((flag&CRDELAY)==I_CR0 || (flag&CRDELAY)==I_CR3) {
  412.     if (!(flag&CRMOD) && (flag&NLDELAY)==I_NL1) {
  413.         oflag |= T_CR1;
  414.     }
  415.     } else if ((flag&CRDELAY)==I_CR1) {
  416.     if (flag&CRMOD) {
  417.         oflag |= T_CR2;
  418.     } else if ((flag&NLDELAY)==I_NL1) {
  419.         oflag |= T_CR1;
  420.     }
  421.     } else if ((flag&CRDELAY)==I_CR2) {
  422.     if (flag&CRMOD) {
  423.         oflag |= T_CR3;
  424.     } else if ((flag&NLDELAY)==I_NL1) {
  425.         oflag |= T_CR1;
  426.     }
  427.     }
  428.     if (flag&VTDELAY) oflag |= FFDLY;
  429.     if (flag&BSDELAY) oflag |= BSDLY;
  430.     if (flag&PRTERA) lflag |= ECHOPRT;
  431.     if (flag&CRTERA) lflag |= ECHOE;
  432.     if (flag&I_TOSTOP) lflag |= TOSTOP;
  433.     if (flag&I_FLUSHO) lflag |= FLUSHO;
  434.     if (flag&NOHANG) cflag |= CLOCAL;
  435.     if (flag&CRTKIL) lflag |= ECHOKE;
  436.     if (flag&CTLECH) lflag |= ECHOCTL;
  437.     if (flag&DECCTQ) iflag &= ~IXANY;
  438.     if (flag&I_NOFLSH) lflag |= T_NOFLSH;
  439.     if (flag&LITOUT) {
  440.     iflag &= ~(ISTRIP|INPCK);
  441.     oflag &= ~OPOST;
  442.     cflag &= CLOCAL;
  443.     cflag |= CREAD|CS8|B9600;
  444.     }
  445.     if (flag&PASS8) {
  446.     iflag &= ~(ISTRIP|INPCK);
  447.     cflag &= CLOCAL;
  448.     cflag |= CREAD|CS8|B9600;
  449.     }
  450.     if (flag&RAW) {
  451.     iflag &= IXOFF|IXANY;
  452.     oflag &= ~OPOST;
  453.     oflag |= ONLRET;
  454.     lflag &= ~(IEXTEN|ISIG|ICANON|ECHOCTL|XCASE);
  455.     cflag &= ~(PARODD|PARENB);
  456.     cflag |= CREAD|CS8|B9600;
  457.     if ((flag&BSDELAY) && ((flag&CRDELAY==I_CR1))) {
  458.         oflag |= T_CR2;
  459.     }
  460.     }
  461.     cflag |= ttyb->sg_ospeed&CBAUD;
  462.     ts->c_iflag = iflag;
  463.     ts->c_oflag = oflag;
  464.     ts->c_cflag = cflag;
  465.     ts->c_lflag = lflag;
  466.     ts->c_line = 0;
  467.     ts->c_cc[VINTR] = tc->t_intrc;
  468.     ts->c_cc[VQUIT] = tc->t_quitc;
  469.     ts->c_cc[VERASE] = ttyb->sg_erase;
  470.     ts->c_cc[VKILL] = ttyb->sg_kill;
  471.     ts->c_cc[VEOF] = tc->t_eofc;
  472.     ts->c_cc[VEOL] = 0;
  473.     ts->c_cc[VEOL2] = 0;
  474.     ts->c_cc[VSWTCH] = 0;
  475.     ts->c_cc[VSTART] = tc->t_startc;
  476.     ts->c_cc[VSTOP] = tc->t_stopc;
  477.     ts->c_cc[VSUSP] = ltc->t_suspc;
  478.     ts->c_cc[VDSUSP] = ltc->t_dsuspc;
  479.     ts->c_cc[VREPRINT] = ltc->t_rprntc;
  480.     ts->c_cc[VDISCARD] = ltc->t_flushc;
  481.     ts->c_cc[VWERASE] = ltc->t_werasc;
  482.     ts->c_cc[VLNEXT] = ltc->t_lnextc;
  483. }
  484.  
  485. /*
  486.  *----------------------------------------------------------------------
  487.  *
  488.  * GetTermInfo --
  489.  *
  490.  *    Get ttyb, lmode, tc, and ltc.
  491.  *
  492.  * Results:
  493.  *    SUCCESS or FAILURE (returns Sprite error)
  494.  *
  495.  * Side effects:
  496.  *    Changes ttyb, etc.
  497.  *     
  498.  *
  499.  *----------------------------------------------------------------------
  500.  */
  501. static int
  502. GetTermInfo(streamPtr, ioctl, ttyb, lmode, tc, ltc)
  503.     Fs_Stream        *streamPtr;
  504.     Fs_IOCParam        *ioctl;
  505.     struct sgttyb *ttyb;
  506.     unsigned int *lmode;
  507.     struct tchars *tc;
  508.     struct ltchars *ltc;
  509. {
  510.     Fs_IOReply          reply;
  511.     ReturnStatus    status;
  512.  
  513.     ioctl->command = IOC_TTY_GET_PARAMS;
  514.     ioctl->outBufSize = sizeof(struct sgttyb);
  515.     ioctl->outBuffer = (Address) ttyb;
  516.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  517.     if (status == SUCCESS) {
  518.     ioctl->command = IOC_TTY_GET_LM;
  519.     ioctl->outBufSize = sizeof(int);
  520.     ioctl->outBuffer = (Address) lmode;
  521.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  522.     }
  523.     if (status == SUCCESS) {
  524.     ioctl->command = IOC_TTY_GET_TCHARS;
  525.     ioctl->outBufSize = sizeof(struct tchars);
  526.     ioctl->outBuffer = (Address) tc;
  527.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  528.     }
  529.     if (status == SUCCESS) {
  530.     ioctl->command = IOC_TTY_GET_LTCHARS;
  531.     ioctl->outBufSize = sizeof(struct ltchars);
  532.     ioctl->outBuffer = (Address) ltc;
  533.     status = Fs_IOControl(streamPtr, ioctl, &reply);
  534.     }
  535.     if (debugFsStubs) {
  536.     printf("GetTermInfo: werase = %x, int = %x\n", ltc->t_werasc,
  537.         tc->t_intrc);
  538.     }
  539.     if (status != SUCCESS && debugFsStubs) {
  540.     printf("GetTermInfo: status %x\n", status);
  541.     }
  542.     return status;
  543. }
  544.  
  545. /*
  546.  *----------------------------------------------------------------------
  547.  *
  548.  * CheckIfPresent --
  549.  *
  550.  *    Check if a prefix is in the prefix table.  This is so we don't
  551.  *    have to do pointless broadcasts for getwd's.
  552.  *
  553.  * Results:
  554.  *    SUCCESS or FAILURE
  555.  *
  556.  * Side effects:
  557.  *     none.
  558.  *
  559.  *----------------------------------------------------------------------
  560.  */
  561. extern int fsprefix_FileNameTrace;
  562. static ReturnStatus
  563. CheckIfPresent(name)
  564.     char *name;
  565. {
  566.     ReturnStatus    status;
  567.     Fs_HandleHeader    *hdrPtr;
  568.     Fs_FileID        rootID;
  569.     char        *lookupName;
  570.     int            serverID=123;
  571.     int            domainType;
  572.     Fsprefix        *prefixPtr;
  573.     Fs_RedirectInfo    *oldInfoPtr = (Fs_RedirectInfo *)NIL;
  574.     Fs_RedirectInfo    *redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  575.     Fs_OpenArgs        openArgs;
  576.     Fs_GetAttrResults    getAttrResults;
  577.     Proc_ControlBlock    *procPtr = Proc_GetEffectiveProc();
  578.     Fs_FileID        ioFileID;
  579.     Fs_Attributes    attrs;
  580.     int            numRedirects=0;
  581.  
  582.     /*
  583.      * This code if from Fs_GetAttributes);
  584.      */
  585.     openArgs.useFlags = FS_FOLLOW;
  586.     openArgs.permissions = 0;
  587.     openArgs.type = FS_FILE;
  588.     openArgs.clientID = rpc_SpriteID;
  589.     Fs_SetIDs(procPtr, &openArgs.id);
  590.     if (procPtr->genFlags & PROC_FOREIGN) {
  591.     openArgs.migClientID = procPtr->peerHostID;
  592.     } else {
  593.     openArgs.migClientID = rpc_SpriteID;
  594.     }
  595.     getAttrResults.attrPtr = &attrs;
  596.     getAttrResults.fileIDPtr = &ioFileID;
  597.  
  598.     /*
  599.      * This loop is out of Fsprefix_LookupOperation
  600.      */
  601.     while (1) {
  602. #if 1
  603.     /*
  604.      * The next loop is from GetPrefix.
  605.      */
  606.     do {
  607.         status = Fsprefix_Lookup(name, FSPREFIX_IMPORTED, FS_LOCALHOST_ID,
  608.             &hdrPtr, &rootID, &lookupName, &serverID, &domainType,
  609.             &prefixPtr);
  610.         if (status == FS_NO_HANDLE) {
  611.         return FAILURE;
  612.         }
  613.     } while (status == FS_NEW_PREFIX);
  614. #else
  615.     status = GetPrefix(name, FS_FOLLOW, &hdrPtr, &rootID, &lookupName,
  616.         &domainType, &prefixPtr);
  617. #endif
  618.     {
  619.         register Fs_LookupArgs *lookupArgsPtr = (Fs_LookupArgs *)&openArgs;
  620.         lookupArgsPtr->prefixID = hdrPtr->fileID;
  621.         lookupArgsPtr->rootID = rootID;
  622.     }
  623.     status = (*fs_DomainLookup[domainType][FS_DOMAIN_GET_ATTR])
  624.         (hdrPtr, lookupName, &openArgs, &getAttrResults, &redirectInfoPtr);
  625.     if (status==SUCCESS) {
  626.         return SUCCESS;
  627.     } else if (status == FS_LOOKUP_REDIRECT) {
  628.         numRedirects++;
  629.         if (numRedirects > FS_MAX_LINKS) {
  630.         printf("Loop\n");
  631.         break;
  632.         }
  633.         status = FsprefixLookupRedirect(redirectInfoPtr, prefixPtr,
  634.             &name);
  635.         if (oldInfoPtr != (Fs_RedirectInfo *)NIL) {
  636.         free((Address)oldInfoPtr);
  637.         }
  638.         oldInfoPtr = redirectInfoPtr;
  639.         redirectInfoPtr = (Fs_RedirectInfo *)NIL;
  640.     } else {
  641.         break;
  642.     }
  643.     }
  644.  
  645.     return FAILURE;
  646. }
  647.  
  648. /*
  649.  *----------------------------------------------------------------------
  650.  *
  651.  * copyin --
  652.  *
  653.  *    Copy a string from user space to a static buffer.
  654.  *
  655.  * Results:
  656.  *    The string.
  657.  *
  658.  * Side effects:
  659.  *     none.
  660.  *
  661.  *----------------------------------------------------------------------
  662.  */
  663. static char *
  664. copyin(string)
  665.     char *string;
  666. {
  667.     static char buf[FS_MAX_PATH_NAME_LENGTH + 1];
  668.     int x;
  669.  
  670.     assert(debugFsStubs);
  671.     Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, string, buf, &x);
  672.     return buf;
  673. }
  674.  
  675. /*
  676.  *----------------------------------------------------------------------
  677.  *
  678.  * Fs_NewReadStub --
  679.  *
  680.  *    The stub for the "read" Unix system call.
  681.  *
  682.  * Results:
  683.  *    Returns -1 on failure.
  684.  *
  685.  * Side effects:
  686.  *    Side effects associated with the system call.
  687.  *     
  688.  *
  689.  *----------------------------------------------------------------------
  690.  */
  691. int
  692. Fs_NewReadStub(streamID, buffer, numBytes)
  693.     int     streamID;    /* descriptor for stream to read */
  694.     char    *buffer;    /* pointer to buffer area */
  695.     int        numBytes;    /* number of bytes to read */
  696. {
  697.     ReturnStatus    status;
  698.     Proc_ControlBlock    *procPtr;
  699.     Fs_Stream        *streamPtr;
  700.     int                 amountRead;
  701.     int                 totalAmountRead;
  702.  
  703.     if (debugFsStubs) {
  704.     printf("Fs_NewReadStub(%d, %d)\n", streamID, numBytes);
  705.     }
  706.     totalAmountRead = 0;
  707.     procPtr = Proc_GetEffectiveProc();
  708.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  709.     if (status != SUCCESS) {
  710.     Mach_SetErrno(Compat_MapCode(status));
  711.     return -1;
  712.     }
  713.     amountRead = numBytes - totalAmountRead;
  714.     if (debugFsStubs) {
  715.         printf("Fs_Read(%x, %x, %x, %x(%d))\n", streamPtr, buffer,
  716.                 streamPtr->offset, &amountRead, amountRead);
  717.     }
  718.     status = Fs_Read(streamPtr, buffer, streamPtr->offset, &amountRead);
  719.     totalAmountRead += amountRead;
  720.     if (status == GEN_ABORTED_BY_SIGNAL) {
  721.         if (debugFsStubs) {
  722.             printf("Fs_Read aborted by signal\n");
  723.         }
  724.         if (totalAmountRead==0) {
  725.             procPtr->unixProgress = PROC_PROGRESS_RESTART;
  726.             return 1122334455; /* Bogus return value */
  727.         }
  728.     } else if (status != SUCCESS) {
  729.         Mach_SetErrno(Compat_MapCode(status));
  730.         return -1;
  731.     }
  732.     return totalAmountRead;
  733. }
  734.  
  735. /*
  736.  *----------------------------------------------------------------------
  737.  *
  738.  * Fs_NewWriteStub --
  739.  *
  740.  *    The stub for the "write" Unix system call.
  741.  *
  742.  * Results:
  743.  *    Returns -1 on failure.
  744.  *
  745.  * Side effects:
  746.  *    Side effects associated with the system call.
  747.  *     
  748.  *
  749.  *----------------------------------------------------------------------
  750.  */
  751. int
  752. Fs_NewWriteStub(streamID, buffer, numBytes)
  753.     int     streamID;    /* descriptor for stream to read */
  754.     char    *buffer;    /* pointer to buffer area */
  755.     int        numBytes;    /* number of bytes to read */
  756. {
  757.     ReturnStatus    status;
  758.     Fs_Stream        *streamPtr;
  759.     int                 writeLength;
  760.     int                 totalAmountWritten;
  761.  
  762.     if (debugFsStubs) {
  763.     printf("Fs_NewWriteStub(%d, %d)\n", streamID, numBytes);
  764.     }
  765.     totalAmountWritten = 0;
  766.     status = Fs_GetStreamPtr(Proc_GetEffectiveProc(), streamID, &streamPtr);
  767.     if (status != SUCCESS) {
  768.     Mach_SetErrno(Compat_MapCode(status));
  769.     return -1;
  770.     }
  771.     writeLength = numBytes - totalAmountWritten;
  772.     status = Fs_Write(streamPtr, buffer, streamPtr->offset, &writeLength);
  773.     totalAmountWritten += writeLength;
  774.     if (status == GEN_ABORTED_BY_SIGNAL) {
  775.         if (debugFsStubs) {
  776.             printf("Fs_Write aborted by signal\n");
  777.         }
  778.         if (totalAmountWritten==0) {
  779.             Proc_GetCurrentProc()->unixProgress = PROC_PROGRESS_RESTART;
  780.             return 1122334455; /* Bogus return value */
  781.         }
  782.     } else if (status != SUCCESS) {
  783.         Mach_SetErrno(Compat_MapCode(status));
  784.         return -1;
  785.     }
  786.     return totalAmountWritten;
  787. }
  788.  
  789. /*
  790.  *----------------------------------------------------------------------
  791.  *
  792.  * Fs_NewOpenStubInt --
  793.  *
  794.  *    The code for the "open" Unix system call.
  795.  *
  796.  * Results:
  797.  *    Returns -1 on failure.
  798.  *
  799.  * Side effects:
  800.  *    Side effects associated with the system call.
  801.  *     
  802.  *
  803.  *----------------------------------------------------------------------
  804.  */
  805. int
  806. Fs_NewOpenStubInt(pathName, unixFlags, permissions)
  807.     int        unixFlags;    /* Unix mode flags. */
  808.     int        permissions;    /* Permission mask to use on creation */
  809.     char    *pathName;    /* The name of the file to open */
  810. {
  811.     ReturnStatus status;    /* result returned by Fs_Open */
  812.     register int useFlags;    /* Sprite version of flags */
  813.     int streamID;
  814.     Fs_Stream         *streamPtr;
  815.  
  816.     /*
  817.      * Convert unixFlags to FS_READ, etc.
  818.      */
  819.     if (debugFsStubs) {
  820.     printf("Fs_NewOpenStubInt(%s, 0x%x, 0x%x)\n",
  821.         copyin(pathName), unixFlags, permissions);
  822.     }
  823.  
  824.     if (unixFlags & FASYNC) {
  825.     printf("open - FASYNC not supported\n");
  826.     Mach_SetErrno(EINVAL);
  827.     return -1;
  828.     }
  829.     if (unixFlags & O_RDWR) {
  830.     useFlags = FS_READ|FS_WRITE;
  831.     } else if (unixFlags & O_WRONLY) {
  832.     useFlags = FS_WRITE;
  833.     } else {
  834.     useFlags = FS_READ;
  835.     }
  836.     if (unixFlags & FNDELAY) {
  837.     useFlags |= FS_NON_BLOCKING;
  838.     }
  839.     if (unixFlags & FAPPEND) {
  840.     useFlags |= FS_APPEND;
  841.     }
  842.     if (unixFlags & FTRUNC) {
  843.     useFlags |= FS_TRUNC;
  844.     }
  845.     if (unixFlags & FEXCL) {
  846.     useFlags |= FS_EXCLUSIVE;
  847.     }
  848.     if (unixFlags & O_MASTER) {
  849.     useFlags |= FS_PDEV_MASTER;
  850.     }
  851.     if (unixFlags & O_PFS_MASTER) {
  852.     useFlags |= FS_PFS_MASTER;
  853.     }
  854.     if (unixFlags & FCREAT) {
  855.     useFlags |= FS_CREATE;
  856.     }
  857.  
  858.     /*
  859.      * Open the file and get a stream descriptor for it.
  860.      */
  861.     useFlags &= ~FS_KERNEL_FLAGS;
  862.     useFlags |= (FS_USER | FS_FOLLOW);
  863.  
  864.     if (debugFsStubs) {
  865.     printf("Fs_NewOpenStubInt: Fs_Open(%s, %x, %x, %x, %x)\n", pathName,
  866.         useFlags, FS_FILE, permissions&0777, &streamPtr);
  867.     }
  868.     status = Fs_Open(pathName, useFlags, FS_FILE,
  869.     permissions & 0777, &streamPtr);
  870.  
  871.     if (status != SUCCESS) {
  872.     if (debugFsStubs) {
  873.         printf("Fs_Open: error %x\n", status);
  874.     }
  875.     Mach_SetErrno(Compat_MapCode(status));
  876.     return -1;
  877.     }
  878.  
  879.     /*
  880.      * Save a pointer to the descriptor in a list kept in the proc table.
  881.      * Its index in the list is the "Stream ID".
  882.      */
  883.     status = Fs_GetStreamID(streamPtr, &streamID);
  884.     if (status != SUCCESS) {
  885.     if (debugFsStubs) {
  886.         printf("open (2) status = %08lx\n", status);
  887.     }
  888.     (void) Fs_Close(streamPtr);
  889.     Mach_SetErrno(Compat_MapCode(status));
  890.     return -1;
  891.     }
  892.     if (debugFsStubs) {
  893.     printf("Fs_NewOpenStubInt: result %d\n", streamID);
  894.     }
  895.     return streamID;
  896. }
  897.  
  898. /*
  899.  *----------------------------------------------------------------------
  900.  *
  901.  * Fs_NewOpenStub --
  902.  *
  903.  *    The stub for the "open" Unix system call.
  904.  *    This routine copies in the pathname and then calls Fs_NewOpenStubInt.
  905.  *
  906.  * Results:
  907.  *    Returns -1 on failure.
  908.  *
  909.  * Side effects:
  910.  *    Side effects associated with the system call.
  911.  *     
  912.  *
  913.  *----------------------------------------------------------------------
  914.  */
  915. int
  916. Fs_NewOpenStub(pathName, unixFlags, permissions)
  917.     char    *pathName;    /* The name of the file to open */
  918.     int        unixFlags;    /* O_RDONLY O_WRONLY O_RDWR O_NDELAY
  919.                  * O_APPEND O_CREAT O_TRUNC O_EXCL */
  920.     int        permissions;    /* Permission mask to use on creation */
  921. {
  922.     int            pathNameLength;
  923.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  924.     Proc_ControlBlock    *procPtr = Proc_GetEffectiveProc();
  925.     /*
  926.      * Copy the name in from user space to the kernel stack.
  927.      */
  928.     procPtr->unixProgress = PROC_PROGRESS_UNIX;
  929.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  930.                &pathNameLength) != SUCCESS) {
  931.     Mach_SetErrno(EACCES);
  932.     if (debugFsStubs) {
  933.         printf("Errno: %x = %d\n", &Proc_GetActualProc()->unixErrno,
  934.             Proc_GetActualProc()->unixErrno);
  935.     }
  936.     return -1;
  937.     }
  938.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  939.     Mach_SetErrno(ENAMETOOLONG);
  940.     return -1;
  941.     }
  942.     return Fs_NewOpenStubInt(newName, unixFlags, permissions);
  943.  
  944. }
  945.  
  946.  
  947. /*
  948.  *----------------------------------------------------------------------
  949.  *
  950.  * Fs_NewCloseStub --
  951.  *
  952.  *    The stub for the "close" Unix system call.
  953.  *
  954.  * Results:
  955.  *    Returns -1 on failure.
  956.  *
  957.  * Side effects:
  958.  *    Side effects associated with the system call.
  959.  *     
  960.  *
  961.  *----------------------------------------------------------------------
  962.  */
  963. int
  964. Fs_NewCloseStub(streamID)
  965.     int streamID;
  966. {
  967.     ReturnStatus status;
  968.  
  969.     if (debugFsStubs) {
  970.     printf("Fs_CloseStub(%d)\n", streamID);
  971.     }
  972.     status = Fs_UserClose(streamID);
  973.  
  974.     if (status != SUCCESS) {
  975.     Mach_SetErrno(Compat_MapCode(status));
  976.     return -1;
  977.     }
  978.     return 0;
  979. }
  980.  
  981. /*
  982.  *----------------------------------------------------------------------
  983.  *
  984.  * Fs_CreatStub --
  985.  *
  986.  *    The stub for the "creat" Unix system call.
  987.  *
  988.  * Results:
  989.  *    Returns -1 on failure.
  990.  *
  991.  * Side effects:
  992.  *    Side effects associated with the system call.
  993.  *     
  994.  *
  995.  *----------------------------------------------------------------------
  996.  */
  997. int
  998. Fs_CreatStub(pathName, permissions)
  999.     char *pathName;        /* The name of the file to create */
  1000.     int permissions;        /* Permission mask to use on creation */
  1001. {
  1002.  
  1003.     if (debugFsStubs) {
  1004.     printf("Fs_CreatStub(%s, 0x%x)\n", copyin(pathName), permissions);
  1005.     }
  1006.     return (Fs_NewOpenStub(pathName, FS_CREATE|FS_TRUNC|FS_WRITE, permissions));
  1007. }
  1008.  
  1009. /*
  1010.  *----------------------------------------------------------------------
  1011.  *
  1012.  * Fs_ReadvStub --
  1013.  *
  1014.  *    The stub for the "readv" Unix system call.
  1015.  *
  1016.  * Results:
  1017.  *    Returns -1 on failure.
  1018.  *
  1019.  * Side effects:
  1020.  *    Side effects associated with the system call.
  1021.  *     
  1022.  *
  1023.  *----------------------------------------------------------------------
  1024.  */
  1025. #define MAX_IOV 16
  1026. int
  1027. Fs_ReadvStub(streamID, iov, iovcnt)
  1028.     int streamID;        /* descriptor for stream to read. */
  1029.     register struct iovec *iov;    /* pointer to array of iovecs. */
  1030.     int iovcnt;            /* number of  iovecs in iov. */
  1031. {
  1032.     int amountRead;             /* place to hold number of bytes read */
  1033.     int totalRead = 0;          /* place to hold total # of bytes read */
  1034.     int i;
  1035.     struct iovec iovCopy[MAX_IOV];      /* Kernel copy of iov */
  1036.     ReturnStatus status;
  1037.  
  1038.     if (debugFsStubs) {
  1039.         printf("Fs_ReadvStub\n");
  1040.     }
  1041.     if (iovcnt<=0 || iovcnt > MAX_IOV) {
  1042.         Mach_SetErrno(EINVAL);
  1043.         return -1;
  1044.     }
  1045.     if (Vm_CopyIn(sizeof(struct iovec)*iovcnt, (Address)iov,
  1046.             (Address)iovCopy) != SUCCESS) {
  1047.         Mach_SetErrno(EFAULT);
  1048.         return -1;
  1049.     }
  1050.     for (i=0; i < iovcnt; i++) {
  1051.         amountRead = Fs_NewReadStub(streamID, iovCopy[i].iov_base,
  1052.                 iovCopy[i].iov_len);
  1053.         if (amountRead == -1) {
  1054.             return -1;
  1055.         }
  1056.         totalRead += amountRead;
  1057.     }
  1058.     return totalRead;
  1059. }
  1060.  
  1061. /*
  1062.  *----------------------------------------------------------------------
  1063.  *
  1064.  * Fs_WritevStub --
  1065.  *
  1066.  *    The stub for the "writev" Unix system call.
  1067.  *
  1068.  * Results:
  1069.  *    Returns -1 on failure.
  1070.  *
  1071.  * Side effects:
  1072.  *    Side effects associated with the system call.
  1073.  *     
  1074.  *
  1075.  *----------------------------------------------------------------------
  1076.  */
  1077. int
  1078. Fs_WritevStub(streamID, iov, iovcnt)
  1079.     int streamID;        /* descriptor for stream to read. */
  1080.     register struct iovec *iov;    /* pointer to array of iovecs. */
  1081.     int iovcnt;            /* number of  iovecs in iov. */
  1082. {
  1083.     int amountWritten;          /* place to hold number of bytes read */
  1084.     int totalWritten = 0;       /* place to hold total # of bytes written */
  1085.     int i;
  1086.     struct iovec iovCopy[MAX_IOV];      /* Kernel copy of iov */
  1087.     ReturnStatus status;
  1088.  
  1089.     if (debugFsStubs) {
  1090.         printf("Fs_WritevStub\n");
  1091.     }
  1092.     if (iovcnt<=0 || iovcnt > MAX_IOV) {
  1093.         Mach_SetErrno(EINVAL);
  1094.         return -1;
  1095.     }
  1096.     if (Vm_CopyIn(sizeof(struct iovec)*iovcnt, (Address)iov,
  1097.             (Address)iovCopy) != SUCCESS) {
  1098.         Mach_SetErrno(EFAULT);
  1099.         return -1;
  1100.     }
  1101.     for (i=0; i < iovcnt; i++) {
  1102.         amountWritten = Fs_NewWriteStub(streamID, iovCopy[i].iov_base,
  1103.                 iovCopy[i].iov_len);
  1104.         if (amountWritten == -1) {
  1105.             return -1;
  1106.         }
  1107.         totalWritten += amountWritten;
  1108.     }
  1109.     return totalWritten;
  1110. }
  1111.  
  1112. /*
  1113.  *----------------------------------------------------------------------
  1114.  *
  1115.  * Fs_LinkStub --
  1116.  *
  1117.  *    The stub for the "link" Unix system call.
  1118.  *
  1119.  * Results:
  1120.  *    Returns -1 on failure.
  1121.  *
  1122.  * Side effects:
  1123.  *    Side effects associated with the system call.
  1124.  *     
  1125.  *
  1126.  *----------------------------------------------------------------------
  1127.  */
  1128. int
  1129. Fs_LinkStub(fileName, linkName)
  1130.     char *fileName;
  1131.     char *linkName;
  1132. {
  1133.     ReturnStatus status;
  1134.     int            fileNameLength;
  1135.     int            linkNameLength;
  1136.     char        newFileName[FS_MAX_PATH_NAME_LENGTH];
  1137.     char        *newLinkName;
  1138.  
  1139.     if (debugFsStubs) {
  1140.     printf("Fs_LinkStub(%s, %s)\n", copyin(fileName), copyin(linkName));
  1141.     }
  1142.  
  1143.     /*
  1144.      * Copy the filename in from user space onto the kernel stack.
  1145.      */
  1146.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, fileName, newFileName,
  1147.                &fileNameLength) != SUCCESS) {
  1148.     Mach_SetErrno(EACCES);
  1149.     return -1;
  1150.     }
  1151.     if (fileNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1152.     Mach_SetErrno(EINVAL);
  1153.     return -1;
  1154.     }
  1155.  
  1156.     /*
  1157.      * Maybe I could put the link name onto the stack as well but I am 
  1158.      * allocing it here because I'm not sure if the stack is big enough.
  1159.      * Should just make the stack bigger I suppose ...
  1160.      */
  1161.     newLinkName = (char  *) malloc(FS_MAX_PATH_NAME_LENGTH);
  1162.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, linkName, newLinkName,
  1163.                &linkNameLength) == SUCCESS) {
  1164.     if (linkNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1165.         status = FS_INVALID_ARG;
  1166.     } else {
  1167.         status = Fs_HardLink(newFileName, newLinkName);
  1168.     }
  1169.     } else {
  1170.     status = SYS_ARG_NOACCESS;
  1171.     }
  1172.     free((Address) newLinkName);
  1173.     if (status != SUCCESS) {
  1174.     Mach_SetErrno(Compat_MapCode(status));
  1175.     return -1;
  1176.     }
  1177.     return 0;
  1178. }
  1179.  
  1180. /*
  1181.  *----------------------------------------------------------------------
  1182.  *
  1183.  * Fs_UnlinkStub --
  1184.  *
  1185.  *    The stub for the "unlink" Unix system call.
  1186.  *
  1187.  * Results:
  1188.  *    Returns -1 on failure.
  1189.  *
  1190.  * Side effects:
  1191.  *    Side effects associated with the system call.
  1192.  *     
  1193.  *
  1194.  *----------------------------------------------------------------------
  1195.  */
  1196. int
  1197. Fs_UnlinkStub(pathName)
  1198.     char *pathName;
  1199. {
  1200.     ReturnStatus status;
  1201.     int            pathNameLength;
  1202.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1203.  
  1204.     if (debugFsStubs) {
  1205.     printf("Fs_UnlinkStub(%s)\n", copyin(pathName));
  1206.     }
  1207.     /*
  1208.      * Copy the name in from user space to the kernel stack.
  1209.      */
  1210.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1211.                &pathNameLength) != SUCCESS) {
  1212.     status = SYS_ARG_NOACCESS;
  1213.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1214.     status = FS_INVALID_ARG;
  1215.     } else {
  1216.     status = Fs_Remove(newName);
  1217.     }
  1218.     if (status != SUCCESS) {
  1219.     Mach_SetErrno(Compat_MapCode(status));
  1220.     return -1;
  1221.     }
  1222.     return 0;
  1223. }
  1224.  
  1225. /*
  1226.  *----------------------------------------------------------------------
  1227.  *
  1228.  * Fs_ChdirStub --
  1229.  *
  1230.  *    The stub for the "chdir" Unix system call.
  1231.  *
  1232.  * Results:
  1233.  *    Returns -1 on failure.
  1234.  *
  1235.  * Side effects:
  1236.  *    Side effects associated with the system call.
  1237.  *     
  1238.  *
  1239.  *----------------------------------------------------------------------
  1240.  */
  1241. int
  1242. Fs_ChdirStub(pathName)
  1243.     char    *pathName;
  1244. {
  1245.     ReturnStatus status;
  1246.     int        pathNameLength;
  1247.     char    newName[FS_MAX_PATH_NAME_LENGTH];
  1248.  
  1249.     if (debugFsStubs) {
  1250.     printf("Fs_ChdirStub(%s)\n", copyin(pathName));
  1251.     }
  1252.  
  1253.     /*
  1254.      * Copy the name in from user space onto the kernel stack.
  1255.      */
  1256.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1257.                &pathNameLength) != SUCCESS) {
  1258.     status = SYS_ARG_NOACCESS;
  1259.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1260.     status = FS_INVALID_ARG;
  1261.     } else {
  1262.     status = Fs_ChangeDir(newName);
  1263.     }
  1264.     if (status != SUCCESS) {
  1265.     Mach_SetErrno(Compat_MapCode(status));
  1266.     return -1;
  1267.     }
  1268.     return 0;
  1269. }
  1270.  
  1271. /*
  1272.  *----------------------------------------------------------------------
  1273.  *
  1274.  * Fs_ChmodStub --
  1275.  *
  1276.  *    The stub for the "chmod" Unix system call.
  1277.  *
  1278.  * Results:
  1279.  *    Returns -1 on failure.
  1280.  *
  1281.  * Side effects:
  1282.  *    Side effects associated with the system call.
  1283.  *     
  1284.  *
  1285.  *----------------------------------------------------------------------
  1286.  */
  1287. int
  1288. Fs_ChmodStub(path, mode)
  1289.     char    *path;
  1290.     int        mode;
  1291. {
  1292.     Fs_Attributes    attr;
  1293.     ReturnStatus    status;
  1294.     int            pathNameLength;
  1295.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1296.  
  1297.     if (debugFsStubs) {
  1298.     printf("Fs_ChmodStub(%s, %x)\n", copyin(path), mode);
  1299.     }
  1300.     /*
  1301.      * Copy the name in from user space onto the kernel stack.
  1302.      */
  1303.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, path, newName,
  1304.                        &pathNameLength) != SUCCESS) {
  1305.     status = SYS_ARG_NOACCESS;
  1306.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1307.     status = FS_INVALID_ARG;
  1308.     } else {
  1309.     attr.permissions = mode;
  1310.     status = Fs_SetAttributes(newName, FS_ATTRIB_FILE, &attr, FS_SET_MODE);
  1311.     }
  1312.     if (status != SUCCESS) {
  1313.     Mach_SetErrno(Compat_MapCode(status));
  1314.     return -1;
  1315.     }
  1316.     return 0;
  1317. }
  1318.  
  1319. /*
  1320.  *----------------------------------------------------------------------
  1321.  *
  1322.  * Fs_FchmodStub --
  1323.  *
  1324.  *    The stub for the "fchmod" Unix system call.
  1325.  *
  1326.  * Results:
  1327.  *    Returns -1 on failure.
  1328.  *
  1329.  * Side effects:
  1330.  *    Side effects associated with the system call.
  1331.  *     
  1332.  *
  1333.  *----------------------------------------------------------------------
  1334.  */
  1335. int
  1336. Fs_FchmodStub(fd, mode)
  1337.     int        fd;
  1338.     int        mode;
  1339. {
  1340.     ReturnStatus    status;
  1341.     Fs_Attributes    attr;
  1342.     Fs_Stream        *streamPtr;
  1343.     Fs_UserIDs        ids;
  1344.     Proc_ControlBlock    *procPtr;
  1345.  
  1346.     if (debugFsStubs) {
  1347.     printf("Fs_FchmodStub(%d, %x)\n", fd, mode);
  1348.     }
  1349.  
  1350.     /*
  1351.      * Map from stream ID to file pointer and get the attributes.
  1352.      */
  1353.     procPtr = Proc_GetEffectiveProc();
  1354.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  1355.     if (status == SUCCESS) {
  1356.     Fs_SetIDs(procPtr, &ids);
  1357.     attr.permissions = mode;
  1358.     status = Fs_SetAttrStream(streamPtr, &attr, &ids, FS_SET_MODE);
  1359.     }
  1360.     if (status != SUCCESS) {
  1361.     Mach_SetErrno(Compat_MapCode(status));
  1362.     return -1;
  1363.     }
  1364.     return 0;
  1365. }
  1366.  
  1367. /*
  1368.  *----------------------------------------------------------------------
  1369.  *
  1370.  * Fs_ChownStub --
  1371.  *
  1372.  *    The stub for the "chown" Unix system call.
  1373.  *
  1374.  * Results:
  1375.  *    Returns -1 on failure.
  1376.  *
  1377.  * Side effects:
  1378.  *    Side effects associated with the system call.
  1379.  *     
  1380.  *
  1381.  *----------------------------------------------------------------------
  1382.  */
  1383. int
  1384. Fs_ChownStub(path, owner, group)
  1385.     char *path;
  1386.     int owner;
  1387.     int group;
  1388. {
  1389.     ReturnStatus    status;    /* result returned by Sprite system calls */
  1390.     Fs_Attributes   attr;     /* struct containing all file attributes.
  1391.                  * only ownership is looked at. */
  1392.     int                pathNameLength;
  1393.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1394.  
  1395.     if (debugFsStubs) {
  1396.     printf("Fs_ChownStub(%s, %d, %d)\n", copyin(path), owner, group);
  1397.     }
  1398.  
  1399.     /*
  1400.      * Copy the name in from user space onto the kernel stack.
  1401.      */
  1402.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, path, newName,
  1403.                &pathNameLength) != SUCCESS) {
  1404.     status = SYS_ARG_NOACCESS;
  1405.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1406.     status = FS_INVALID_ARG;
  1407.     } else {
  1408.     attr.uid = owner;
  1409.     attr.gid = group;
  1410.     status = Fs_SetAttributes(newName, FS_ATTRIB_LINK, &attr, FS_SET_OWNER);
  1411.     }
  1412.     if (status != SUCCESS) {
  1413.     Mach_SetErrno(Compat_MapCode(status));
  1414.     return -1;
  1415.     }
  1416.     return 0;
  1417. }
  1418.  
  1419. /*
  1420.  *----------------------------------------------------------------------
  1421.  *
  1422.  * Fs_FchownStub --
  1423.  *
  1424.  *    The stub for the "fchown" Unix system call.
  1425.  *
  1426.  * Results:
  1427.  *    Returns -1 on failure.
  1428.  *
  1429.  * Side effects:
  1430.  *    Side effects associated with the system call.
  1431.  *     
  1432.  *
  1433.  *----------------------------------------------------------------------
  1434.  */
  1435. int
  1436. Fs_FchownStub(fd, owner, group)
  1437.     int fd;
  1438.     int owner;
  1439.     int group;
  1440. {
  1441.     ReturnStatus status;    /* result returned by Sprite system calls */
  1442.     Fs_Attributes attr;     /* struct containing all file attributes.
  1443.                  * only ownership is looked at. */
  1444.     Fs_Stream            *streamPtr;
  1445.     Fs_UserIDs            ids;
  1446.     Proc_ControlBlock        *procPtr;
  1447.  
  1448.     if (debugFsStubs) {
  1449.     printf("Fs_FchownStub(%d, %d, %d)\n", fd,  owner, group);
  1450.     }
  1451.     /*
  1452.      * Map from stream ID to file pointer and get the attributes.
  1453.      */
  1454.     procPtr = Proc_GetEffectiveProc();
  1455.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  1456.     if (status == SUCCESS) {
  1457.     Fs_SetIDs(procPtr, &ids);
  1458.     attr.uid = owner;
  1459.     attr.gid = group;
  1460.     status = Fs_SetAttrStream(streamPtr, &attr, &ids, FS_SET_OWNER);
  1461.     }
  1462.     if (status != SUCCESS) {
  1463.     Mach_SetErrno(Compat_MapCode(status));
  1464.     return -1;
  1465.     }
  1466.     return 0;
  1467. }
  1468.  
  1469. /*
  1470.  *----------------------------------------------------------------------
  1471.  *
  1472.  * Fs_IoctlInt --
  1473.  *
  1474.  *    Do an ioctl.  This routine initalizes the ioctl structure and
  1475.  *    performs the ioctl.
  1476.  *
  1477.  * Results:
  1478.  *    Returns -1 on failure.  Sets errno on failure.  Also returns error
  1479.  *    through err.
  1480.  *
  1481.  * Side effects:
  1482.  *    Side effects associated with the ioctl.
  1483.  *     
  1484.  *
  1485.  *----------------------------------------------------------------------
  1486.  */
  1487. int
  1488. Fs_IoctlInt(streamID, command, inBufSize, inBuf, outBufSize, outBuf,
  1489.     reply, err)
  1490.     int            streamID;
  1491.     int            command;
  1492.     Address        inBuf, outBuf;
  1493.     int            inBufSize, outBufSize;
  1494.     Fs_IOReply          *reply;
  1495.     int            *err;
  1496. {
  1497.     Fs_IOCParam         ioctl;
  1498.     Proc_ControlBlock *procPtr;
  1499.     ReturnStatus status;
  1500.     Fs_Stream *streamPtr;
  1501.  
  1502.     if (debugFsStubs) {
  1503.     printf("Fs_IoctlInt(%d, %d, %x, %x, %x, %x, %x, %x)\n", streamID,
  1504.         command, inBufSize ,inBuf, outBufSize, outBuf, reply, err);
  1505.     }
  1506.     procPtr = Proc_GetEffectiveProc();
  1507.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  1508.     if (status == SUCCESS) {
  1509.     ioctl.command = command;
  1510.     ioctl.inBuffer = inBuf;
  1511.     ioctl.inBufSize = inBufSize;
  1512.     ioctl.outBuffer = outBuf;
  1513.     ioctl.outBufSize = outBufSize;
  1514.     ioctl.format = mach_Format;
  1515.     ioctl.procID = procPtr->processID;
  1516.     ioctl.familyID = procPtr->familyID;
  1517.     ioctl.uid = procPtr->effectiveUserID;
  1518.     ioctl.flags = 0;
  1519.     status = Fs_IOControl(streamPtr, &ioctl, reply);
  1520.     }
  1521.     if (status != SUCCESS) {
  1522.     if (debugFsStubs) {
  1523.         printf("Ioctl %x failed\n", command);
  1524.     }
  1525.     *err= Compat_MapCode(status);
  1526.     Mach_SetErrno(*err);
  1527.     return -1;
  1528.     }
  1529.     return 0;
  1530. }
  1531.  
  1532. /*
  1533.  *----------------------------------------------------------------------
  1534.  *
  1535.  * Fs_LseekStub --
  1536.  *
  1537.  *    The stub for the "lseek" Unix system call.
  1538.  *
  1539.  * Results:
  1540.  *    Returns -1 on failure.
  1541.  *
  1542.  * Side effects:
  1543.  *    Side effects associated with the system call.
  1544.  *     
  1545.  *
  1546.  *----------------------------------------------------------------------
  1547.  */
  1548. int
  1549. Fs_LseekStub(streamID, offset, whence)
  1550.     int streamID;            /* array of stream identifiers */
  1551.     long offset;
  1552.     int whence;
  1553. {
  1554.     int    status;
  1555.     /* The following nonsense is because the SOSP91 code tacks some
  1556.      * stuff on the end of the Ioc_RepositionArgs.  If we don't have
  1557.      * memory there, it is bad.
  1558.      */
  1559. #define inArgs (*inArgsPtr)
  1560.     char buf[sizeof(Ioc_RepositionArgs)+12];
  1561.     Ioc_RepositionArgs *inArgsPtr = (Ioc_RepositionArgs *)buf;
  1562.  
  1563.     long                retVal;
  1564.     int            err;
  1565.     Fs_IOReply          reply;
  1566.  
  1567.     if (debugFsStubs) {
  1568.     printf("Fs_LseekStub(%d, 0x%x, %d)\n", streamID, offset, whence);
  1569.     }
  1570.     switch(whence) {
  1571.  
  1572.     case L_SET:
  1573.         inArgs.base = IOC_BASE_ZERO;
  1574.         break;
  1575.  
  1576.     case L_INCR:
  1577.         inArgs.base = IOC_BASE_CURRENT;
  1578.         break;
  1579.  
  1580.     case L_XTND:
  1581.         inArgs.base = IOC_BASE_EOF;
  1582.         break;
  1583.  
  1584.     default:
  1585.         Mach_SetErrno(EINVAL);
  1586.         return -1;
  1587.     }
  1588.     inArgs.offset = offset;
  1589.     if (debugFsStubs) {
  1590.     printf("ioctl: %d, %d\n", inArgs.offset, inArgs.base);
  1591.     }
  1592.     status = Fs_IoctlInt(streamID, IOC_REPOSITION, sizeof(Ioc_RepositionArgs),
  1593.         (Address)&inArgs, sizeof(retVal), (Address)&retVal, &reply, &err);
  1594.     if (status < 0) {
  1595.     return -1;
  1596.     } else {
  1597.     return retVal;
  1598.     }
  1599. }
  1600.  
  1601. /*
  1602.  *----------------------------------------------------------------------
  1603.  *
  1604.  * Fs_AccessStub --
  1605.  *
  1606.  *    The stub for the "access" Unix system call.
  1607.  *
  1608.  * Results:
  1609.  *    Returns -1 on failure.
  1610.  *
  1611.  * Side effects:
  1612.  *    Side effects associated with the system call.
  1613.  *     
  1614.  *
  1615.  *----------------------------------------------------------------------
  1616.  */
  1617. int
  1618. Fs_AccessStub(pathName, mode)
  1619.     char *pathName;        /* The name of the file to open */
  1620.     int     mode;            /* access mode to test for */
  1621. {
  1622.     ReturnStatus status;
  1623.     int spriteMode;
  1624.  
  1625.     if (debugFsStubs) {
  1626.     printf("Fs_AccessStub(%s, %d)\n", copyin(pathName), mode);
  1627.     }
  1628.     if (mode == F_OK) {
  1629.     spriteMode = FS_EXISTS;
  1630.     } else {
  1631.     spriteMode = ((mode&R_OK)?FS_READ:0) | ((mode&W_OK)?FS_WRITE:0) |
  1632.         ((mode&X_OK)?FS_EXECUTE:0);
  1633.     }
  1634.     status = Fs_CheckAccess(pathName, spriteMode, TRUE);
  1635.     if (status != SUCCESS) {
  1636.     Mach_SetErrno(Compat_MapCode(status));
  1637.     return -1;
  1638.     }
  1639.     return 0;
  1640. }
  1641.  
  1642.  
  1643. /*
  1644.  *----------------------------------------------------------------------
  1645.  *
  1646.  * Fs_FsyncStub --
  1647.  *
  1648.  *    The stub for the "fsync" Unix system call.
  1649.  *
  1650.  * Results:
  1651.  *    Returns -1 on failure.
  1652.  *
  1653.  * Side effects:
  1654.  *    Side effects associated with the system call.
  1655.  *     
  1656.  *
  1657.  *----------------------------------------------------------------------
  1658.  */
  1659. int
  1660. Fs_FsyncStub(fd)
  1661.     int fd;
  1662. {
  1663.     ReturnStatus status;
  1664.  
  1665.     if (debugFsStubs) {
  1666.     printf("Fs_FsyncStub\n");
  1667.     }
  1668.     status = Fs_FileWriteBackStub(fd, -1, -1, 1);
  1669.     if (status != SUCCESS) {
  1670.     Mach_SetErrno(Compat_MapCode(status));
  1671.     return -1;
  1672.     }
  1673.     return 0;
  1674. }
  1675.  
  1676.  
  1677.  
  1678.  
  1679. /*
  1680.  *----------------------------------------------------------------------
  1681.  *
  1682.  * Fs_StatStub --
  1683.  *
  1684.  *    The stub for the "stat" Unix system call.
  1685.  *
  1686.  * Results:
  1687.  *    Returns -1 on failure.
  1688.  *
  1689.  * Side effects:
  1690.  *    Side effects associated with the system call.
  1691.  *     
  1692.  *
  1693.  *----------------------------------------------------------------------
  1694.  */
  1695. int
  1696. Fs_StatStub(pathName, attrsBufPtr)
  1697.     char *pathName;        /* The name of the file to stat */
  1698.     struct stat *attrsBufPtr;    /* ptr to buffer to hold attributes in 
  1699.                    Unix format */
  1700. {
  1701.     ReturnStatus     status;    /* status returned by Fs_GetAttributes */
  1702.     Fs_Attributes    spriteAttrs;    /* buffer for attributes using
  1703.                        Sprite format. */
  1704.     struct stat        tmpAttrsBuf;
  1705.     int            pathNameLength;
  1706.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1707.  
  1708.     if (debugFsStubs) {
  1709.     printf("Fs_StatStub(%s)\n", copyin(pathName));
  1710.     }
  1711.     /*
  1712.      * Copy the name in from user space onto the kernel stack.
  1713.      */
  1714.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1715.                &pathNameLength) != SUCCESS) {
  1716.     status = SYS_ARG_NOACCESS;
  1717.     if (debugFsStubs) {
  1718.         printf("Fs_StatStub: arg no access\n");
  1719.     }
  1720.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1721.     status = FS_INVALID_ARG;
  1722.     if (debugFsStubs) {
  1723.         printf("Fs_StatStub: len\n");
  1724.     }
  1725.     } else {
  1726.     if (CheckIfPresent(newName) != SUCCESS) {
  1727.         Mach_SetErrno(ENOENT);
  1728.         return -1;
  1729.     }
  1730.     status = Fs_GetAttributes(newName, FS_ATTRIB_FILE, &spriteAttrs);
  1731.     if (status == SUCCESS) {
  1732.         CvtSpriteToUnixAtts(&spriteAttrs, &tmpAttrsBuf);
  1733.         /*
  1734.          * The Unix stat structure is 8 bytes shorter than in stat.h
  1735.          */
  1736.         status = Vm_CopyOut(sizeof(struct stat)-8, (Address) &tmpAttrsBuf,
  1737.             (Address) attrsBufPtr);
  1738.     }
  1739.     }
  1740.     if (status != SUCCESS) {
  1741.     if (debugFsStubs) {
  1742.         printf("Fs_StatStub: failure\n");
  1743.     }
  1744.     Mach_SetErrno(Compat_MapCode(status));
  1745.     return -1;
  1746.     }
  1747.     return 0;
  1748. }
  1749.  
  1750.  
  1751. /*
  1752.  *----------------------------------------------------------------------
  1753.  *
  1754.  * Fs_LstatStub --
  1755.  *
  1756.  *    The stub for the "lstat" Unix system call.
  1757.  *
  1758.  * Results:
  1759.  *    Returns -1 on failure.
  1760.  *
  1761.  * Side effects:
  1762.  *    Side effects associated with the system call.
  1763.  *     
  1764.  *
  1765.  *----------------------------------------------------------------------
  1766.  */
  1767. int
  1768. Fs_LstatStub(pathName, attrsBufPtr)
  1769.     char *pathName;        /* The name of the file to stat */
  1770.     struct stat *attrsBufPtr;    /* ptr to buffer to hold attributes in 
  1771.                    Unix format */
  1772. {
  1773.     ReturnStatus     status;    /* status returned by Fs_GetAttributes */
  1774.     Fs_Attributes    spriteAttrs;    /* buffer for attributes using
  1775.                        Sprite format. */
  1776.     struct stat        tmpAttrsBuf;
  1777.     int            pathNameLength;
  1778.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  1779.  
  1780.     if (debugFsStubs) {
  1781.     printf("Fs_LstatStub(%s)\n", copyin(pathName));
  1782.     }
  1783.     /*
  1784.      * Copy the name in from user space onto the kernel stack.
  1785.      */
  1786.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  1787.                &pathNameLength) != SUCCESS) {
  1788.     status = SYS_ARG_NOACCESS;
  1789.     } else if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  1790.     status = FS_INVALID_ARG;
  1791.     } else {
  1792.     status = Fs_GetAttributes(newName, FS_ATTRIB_LINK, &spriteAttrs);
  1793.     if (CheckIfPresent(newName) == SUCCESS) {
  1794.         /*
  1795.          * See if we just got a remote link.  If so turn around and do
  1796.          * a normal stat because in compatibility mode we want to
  1797.          * follow remote links.
  1798.          */
  1799.         if (spriteAttrs.type == FS_REMOTE_LINK) {
  1800.            status = Fs_GetAttributes(newName,FS_ATTRIB_FILE,&spriteAttrs);
  1801.         }
  1802.     } else {
  1803.         if (debugFsStubs) {
  1804.         printf("Skipping stat of remote link\n");
  1805.         }
  1806.     }
  1807.     if (status == SUCCESS) {
  1808.         CvtSpriteToUnixAtts(&spriteAttrs, &tmpAttrsBuf);
  1809.         /*
  1810.          * The Unix stat structure is 8 bytes shorter than in stat.h
  1811.          */
  1812.         status = Vm_CopyOut(sizeof(struct stat)-8, (Address) &tmpAttrsBuf,
  1813.             (Address) attrsBufPtr);
  1814.     }
  1815.     }
  1816.     if (status != SUCCESS) {
  1817.     Mach_SetErrno(Compat_MapCode(status));
  1818.     return -1;
  1819.     }
  1820.     return 0;
  1821. }
  1822.  
  1823. /*
  1824.  *----------------------------------------------------------------------
  1825.  *
  1826.  * Fs_FstatStub --
  1827.  *
  1828.  *    The stub for the "fstat" Unix system call.
  1829.  *
  1830.  * Results:
  1831.  *    Returns -1 on failure.
  1832.  *
  1833.  * Side effects:
  1834.  *    Side effects associated with the system call.
  1835.  *     
  1836.  *
  1837.  *----------------------------------------------------------------------
  1838.  */
  1839. int
  1840. Fs_FstatStub(streamID, attrsBufPtr)
  1841.     int    streamID;        /* The name of the file to stat */
  1842.     struct stat *attrsBufPtr;    /* ptr to user buffer to hold attributes in 
  1843.                    Unix format */
  1844. {
  1845.     ReturnStatus     status;    /* status returned by Fs_GetAttributes */
  1846.     Fs_Attributes    spriteAttrs;    /* buffer for attributes using
  1847.                        Sprite format. */
  1848.     struct stat        tmpAttrsBuf;
  1849.     Fs_Stream        *streamPtr;
  1850.  
  1851.     if (debugFsStubs) {
  1852.     printf("Fs_FstatStub(%d)\n", streamID);
  1853.     }
  1854.     status = Fs_GetStreamPtr(Proc_GetEffectiveProc(), streamID, &streamPtr);
  1855.     if (status == SUCCESS) {
  1856.     status = Fs_GetAttrStream(streamPtr, &spriteAttrs);
  1857.     if (status == SUCCESS) {
  1858.         CvtSpriteToUnixAtts(&spriteAttrs, &tmpAttrsBuf);
  1859.         /*
  1860.          * The Unix stat structure is 8 bytes shorter than in stat.h
  1861.          */
  1862.         status = Vm_CopyOut(sizeof(struct stat)-8, (Address) &tmpAttrsBuf,
  1863.             (Address) attrsBufPtr);
  1864.     }
  1865.     }
  1866.     if (status != SUCCESS) {
  1867.     if (debugFsStubs) {
  1868.         printf("Fs_Fstat failed\n");
  1869.     }
  1870.     Mach_SetErrno(Compat_MapCode(status));
  1871.     return -1;
  1872.     }
  1873.     return 0;
  1874. }
  1875.  
  1876. /*
  1877.  *----------------------------------------------------------------------
  1878.  *
  1879.  * Fs_DupStub --
  1880.  *
  1881.  *    The stub for the "dup" Unix system call.
  1882.  *
  1883.  * Results:
  1884.  *    Returns -1 on failure.
  1885.  *
  1886.  * Side effects:
  1887.  *    Side effects associated with the system call.
  1888.  *     
  1889.  *
  1890.  *----------------------------------------------------------------------
  1891.  */
  1892. int
  1893. Fs_DupStub(oldStreamID)
  1894.     int oldStreamID;
  1895. {
  1896.     ReturnStatus    status;
  1897.     int         newStreamID;
  1898.  
  1899.     if (debugFsStubs) {
  1900.     printf("Fs_DupStub(%d)\n", oldStreamID);
  1901.     }
  1902.     newStreamID = FS_ANYID;
  1903.     status = Fs_GetNewID(oldStreamID, &newStreamID);
  1904.     if (status != SUCCESS) {
  1905.     Mach_SetErrno(Compat_MapCode(status));
  1906.     return -1;
  1907.     }
  1908.     return newStreamID;
  1909. }
  1910.  
  1911. /*
  1912.  *----------------------------------------------------------------------
  1913.  *
  1914.  * Fs_Dup2Stub --
  1915.  *
  1916.  *    The stub for the "dup2" Unix system call.
  1917.  *
  1918.  * Results:
  1919.  *    Returns -1 on failure.
  1920.  *
  1921.  * Side effects:
  1922.  *    Side effects associated with the system call.
  1923.  *     
  1924.  *
  1925.  *----------------------------------------------------------------------
  1926.  */
  1927. int
  1928. Fs_Dup2Stub(oldStreamID, newStreamID)
  1929.     int oldStreamID;        /* original stream identifier */
  1930.     int newStreamID;        /* new stream identifier */
  1931. {
  1932.     ReturnStatus    status;
  1933.  
  1934.     if (debugFsStubs) {
  1935.     printf("Fs_Dup2Stub(%d, %d)\n", oldStreamID, newStreamID);
  1936.     }
  1937.     status = Fs_GetNewID(oldStreamID, &newStreamID);
  1938.     if (status != SUCCESS) {
  1939.     Mach_SetErrno(Compat_MapCode(status));
  1940.     return -1;
  1941.     }
  1942.     return newStreamID;
  1943. }
  1944.  
  1945. /*
  1946.  *----------------------------------------------------------------------
  1947.  *
  1948.  * Fs_PipeStub --
  1949.  *
  1950.  *    The stub for the "pipe" Unix system call.
  1951.  *    This code is ripped off from Fs_CreatePipeStub.
  1952.  *
  1953.  * Results:
  1954.  *    Returns -1 on failure.
  1955.  *
  1956.  * Side effects:
  1957.  *    Creates a pipe.
  1958.  *     
  1959.  *
  1960.  *----------------------------------------------------------------------
  1961.  */
  1962. int
  1963. Fs_PipeStub()
  1964. {
  1965.     ReturnStatus    status;
  1966.     Fs_Stream        *inStreamPtr, *outStreamPtr;
  1967.     int            inStreamID, outStreamID;
  1968.  
  1969.     if (debugFsStubs) {
  1970.     printf("Fs_PipeStub\n");
  1971.     }
  1972.     status = Fsio_CreatePipe(&inStreamPtr, &outStreamPtr);
  1973.     if (status != SUCCESS) {
  1974.     Mach_SetErrno(Compat_MapCode(status));
  1975.     return -1;
  1976.     }
  1977.     inStreamPtr->flags |= FS_USER;
  1978.     outStreamPtr->flags |= FS_USER;
  1979.  
  1980.     /*
  1981.      * Get stream ids for the two streams.
  1982.      */
  1983.     status = Fs_GetStreamID(inStreamPtr, &inStreamID);
  1984.     if (status != SUCCESS) {
  1985.         (void) Fs_Close(inStreamPtr);
  1986.         (void) Fs_Close(outStreamPtr);
  1987.     Mach_SetErrno(Compat_MapCode(status));
  1988.     return -1;
  1989.     }
  1990.     status = Fs_GetStreamID(outStreamPtr, &outStreamID);
  1991.     if (status != SUCCESS) {
  1992.         Fs_ClearStreamID(inStreamID, (Proc_ControlBlock *)NIL);
  1993.         (void) Fs_Close(inStreamPtr);
  1994.         (void) Fs_Close(outStreamPtr);
  1995.     Mach_SetErrno(Compat_MapCode(status));
  1996.     return -1;
  1997.     }
  1998.     if (debugFsStubs) {
  1999.     printf("Fs_PipeStub: return %d, %d\n", inStreamID, outStreamID);
  2000.     }
  2001.     Mach_Return2(outStreamID);
  2002.     return inStreamID;
  2003. }
  2004.  
  2005. /*
  2006.  *----------------------------------------------------------------------
  2007.  *
  2008.  * Fs_SymlinkStub --
  2009.  *
  2010.  *    The stub for the "symlink" Unix system call.
  2011.  *
  2012.  * Results:
  2013.  *    Returns -1 on failure.
  2014.  *
  2015.  * Side effects:
  2016.  *    Side effects associated with the system call.
  2017.  *     
  2018.  *
  2019.  *----------------------------------------------------------------------
  2020.  */
  2021. int
  2022. Fs_SymlinkStub(target, link) 
  2023.     char *target;
  2024.     char *link;
  2025. {
  2026.     ReturnStatus    status;
  2027.  
  2028.     if (debugFsStubs) {
  2029.     printf("Fs_SymlinkStub\n");
  2030.     }
  2031.     status = Fs_SymLinkStub(target, link, FALSE);
  2032.     if (status != SUCCESS) {
  2033.     Mach_SetErrno(Compat_MapCode(status));
  2034.     return -1;
  2035.     }
  2036.     return 0;
  2037. }
  2038.  
  2039. /*
  2040.  *----------------------------------------------------------------------
  2041.  *
  2042.  * Fs_ReadlinkStub --
  2043.  *
  2044.  *    The stub for the "readlink" Unix system call.
  2045.  *
  2046.  * Results:
  2047.  *    Returns -1 on failure.
  2048.  *
  2049.  * Side effects:
  2050.  *    Side effects associated with the system call.
  2051.  *     
  2052.  *
  2053.  *----------------------------------------------------------------------
  2054.  */
  2055. int
  2056. Fs_ReadlinkStub(linkName, buffer, bufSize)
  2057.     char *linkName;        /* name of link file to read */
  2058.     char *buffer;        /* pointer to buffer area */
  2059.     int   bufSize;        /* number of bytes to read */
  2060. {
  2061.     ReturnStatus    status;
  2062.     Fs_Stream        *streamPtr;
  2063.     int            linkNameLength;
  2064.     char        newLinkName[FS_MAX_PATH_NAME_LENGTH];
  2065.     int             linkSize;
  2066.  
  2067.     if (debugFsStubs) {
  2068.     printf("Fs_ReadlinkStub\n");
  2069.     }
  2070.     /*
  2071.      * Copy the name in from user space onto the kernel stack.
  2072.      */
  2073.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, linkName, newLinkName,
  2074.                &linkNameLength) != SUCCESS) {
  2075.     status = SYS_ARG_NOACCESS;
  2076.     } else if (linkNameLength == FS_MAX_PATH_NAME_LENGTH) {
  2077.     status = FS_INVALID_ARG;
  2078.     } else {
  2079.     status = Fs_Open(newLinkName, FS_READ | FS_USER,
  2080.                      FS_SYMBOLIC_LINK|FS_REMOTE_LINK, 0, &streamPtr);
  2081.     if (status == SUCCESS) {
  2082.         status = Fs_Read(streamPtr, buffer, 0, &bufSize);
  2083.         if (status == SUCCESS) {
  2084.         /*
  2085.          * Sprite's link count includes the terminating null character
  2086.          * in the character count return while Unix doesn't.  Make our
  2087.          * count backward-compatible with Unix.
  2088.          */
  2089.         if (buffer[bufSize-1] == '\0') {
  2090.             bufSize--;
  2091.         }
  2092.         status = Proc_ByteCopy(TRUE, sizeof(int), (Address)&bufSize, 
  2093.                                (Address) &linkSize);
  2094.         }
  2095.         (void)Fs_Close(streamPtr);
  2096.     }
  2097.     }
  2098.     if (status != SUCCESS) {
  2099.     Mach_SetErrno(Compat_MapCode(status));
  2100.     return -1;
  2101.     }
  2102.     return bufSize;
  2103. }
  2104.  
  2105. /*
  2106.  *----------------------------------------------------------------------
  2107.  *
  2108.  * Fs_IoctlStub --
  2109.  *
  2110.  *    The stub for the "ioctl" Unix system call.
  2111.  *
  2112.  * Results:
  2113.  *    Returns -1 on failure.
  2114.  *
  2115.  * Side effects:
  2116.  *    Side effects associated with the system call.
  2117.  *     
  2118.  *
  2119.  *----------------------------------------------------------------------
  2120.  */
  2121. int
  2122. Fs_IoctlStub(streamID, request, buf)
  2123.     int  streamID;
  2124.     int  request;
  2125.     char *buf;
  2126. {
  2127.     Proc_ControlBlock   *procPtr;
  2128.     Fs_Stream             *streamPtr;
  2129.     ReturnStatus        status = SUCCESS;
  2130.     Fs_IOCParam         ioctl;
  2131.     Fs_IOReply          reply;
  2132.     Mach_State          *machStatePtr;
  2133.     int                 flags;
  2134.  
  2135.     if (debugFsStubs) {
  2136.     printf("Fs_IoctlStub(%d, 0x%x)\n", streamID, request);
  2137.     }
  2138.  
  2139.     /*
  2140.      * Get a stream pointer.
  2141.      */
  2142.     procPtr = Proc_GetEffectiveProc();
  2143.     machStatePtr = procPtr->machStatePtr;
  2144.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  2145.     if (status != SUCCESS) {
  2146.     Mach_SetErrno(Compat_MapCode(status));
  2147.     return -1;
  2148.     }
  2149.     if (!Fsutil_HandleValid(streamPtr->ioHandlePtr)) {
  2150.     Mach_SetErrno(EBADF);
  2151.     return -1;
  2152.     }
  2153.     ioctl.format = mach_Format;
  2154.     ioctl.procID = procPtr->processID;
  2155.     ioctl.familyID = procPtr->familyID;
  2156.     ioctl.uid = procPtr->effectiveUserID;
  2157.     ioctl.inBuffer = NULL;
  2158.     ioctl.inBufSize = 0;
  2159.     ioctl.outBuffer = NULL;
  2160.     ioctl.outBufSize = 0;
  2161.     ioctl.flags = 0;
  2162.     switch (request) {
  2163.  
  2164.     case FIOCLEX:
  2165.     if (debugFsStubs) {
  2166.                 printf("ioctl: FIOCLEX\n");
  2167.                 }
  2168.     ioctl.command = IOC_SET_BITS;
  2169.     ioctl.inBufSize = sizeof(int);
  2170.     ioctl.inBuffer = (Address) &flags;
  2171.     flags = IOC_CLOSE_ON_EXEC;
  2172.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2173.     procPtr->fsPtr->streamFlags[streamID] |= FS_CLOSE_ON_EXEC;
  2174.     break;
  2175.  
  2176.     case FIONCLEX:
  2177.     if (debugFsStubs) {
  2178.                 printf("ioctl: FIONCLEX\n");
  2179.                 }
  2180.     ioctl.command = IOC_CLEAR_BITS;
  2181.     ioctl.inBufSize = sizeof(int);
  2182.     ioctl.inBuffer = (Address) &flags;
  2183.     flags = IOC_CLOSE_ON_EXEC;
  2184.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2185.     procPtr->fsPtr->streamFlags[streamID] |= FS_CLOSE_ON_EXEC;
  2186.     break;
  2187.  
  2188.  
  2189.     case FIONREAD: {
  2190.     int result;
  2191.     if (debugFsStubs) {
  2192.                 printf("ioctl: FIONREAD\n");
  2193.                 }
  2194.     ioctl.command = IOC_NUM_READABLE;
  2195.     ioctl.outBuffer = (Address) &result;
  2196.     ioctl.outBufSize = sizeof(int);
  2197.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2198.     if (status == SUCCESS) {
  2199.         status = Vm_CopyOut(sizeof(int), (Address) &result, buf);
  2200.     }
  2201.     break;
  2202.     }
  2203.  
  2204.  
  2205.     case FIONBIO:
  2206.     if (debugFsStubs) {
  2207.                 printf("ioctl: FIONBIO\n");
  2208.                 }
  2209.     if (Vm_CopyIn(4, buf, (Address) &flags) != SUCCESS) {
  2210.         Mach_SetErrno(EINVAL);
  2211.         return -1;
  2212.     }
  2213.     if (flags) {
  2214.         ioctl.command = IOC_SET_BITS;
  2215.     } else {
  2216.         ioctl.command = IOC_CLEAR_BITS;
  2217.     }
  2218.     ioctl.inBufSize = sizeof(int);
  2219.     ioctl.inBuffer = (Address) &flags;
  2220.     flags = IOC_NON_BLOCKING;
  2221.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2222.     break;
  2223.  
  2224.     case FIOASYNC:
  2225.     if (debugFsStubs) {
  2226.                 printf("ioctl: FIOASYNC\n");
  2227.                 }
  2228.     if (Vm_CopyIn(4, buf, (Address) &flags) != SUCCESS) {
  2229.         Mach_SetErrno(EINVAL);
  2230.         return -1;
  2231.     }
  2232.     if (flags)  {
  2233.         ioctl.command = IOC_SET_BITS;
  2234.     } else {
  2235.         ioctl.command = IOC_CLEAR_BITS;
  2236.     }
  2237.     ioctl.inBufSize = sizeof(int);
  2238.     ioctl.inBuffer = (Address) &flags;
  2239.     flags = IOC_ASYNCHRONOUS;
  2240.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2241.     break;
  2242.  
  2243.     case FIOGETOWN:
  2244.     case SIOCGPGRP:
  2245.     case TIOCGPGRP: {
  2246.         Ioc_Owner owner;
  2247.  
  2248.         if (debugFsStubs) {
  2249.         printf("ioctl: FIOGETOWN\n");
  2250.         }
  2251.         ioctl.command = IOC_GET_OWNER;
  2252.         ioctl.outBuffer = (Address) &owner;
  2253.         ioctl.outBufSize = sizeof(owner);
  2254.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2255.         if (status != SUCCESS) {
  2256.         Mach_SetErrno(Compat_MapCode(status));
  2257.         return -1;
  2258.         }
  2259.         status = Vm_CopyOut(sizeof(int), (Address) &owner.id, buf);
  2260.         if (status != SUCCESS) {
  2261.         Mach_SetErrno(EINVAL);
  2262.         return -1;
  2263.         }
  2264.         }
  2265.         break;
  2266.  
  2267.     case FIOSETOWN:
  2268.     case SIOCSPGRP:
  2269.     case TIOCSPGRP: {
  2270.         Ioc_Owner owner;
  2271.  
  2272.         if (debugFsStubs) {
  2273.                 printf("ioctl: FIOSETOWN\n");
  2274.         }
  2275.         status = Vm_CopyIn(sizeof(int), buf, (Address) &owner.id);
  2276.         if (status != SUCCESS) {
  2277.         Mach_SetErrno(EINVAL);
  2278.         return -1;
  2279.         }
  2280.         owner.procOrFamily = IOC_OWNER_FAMILY;
  2281.         ioctl.command = IOC_SET_OWNER;
  2282.         ioctl.inBuffer = (Address) &owner;
  2283.         ioctl.inBufSize = sizeof(owner);
  2284.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2285.         }
  2286.     break;
  2287.  
  2288.     /* 
  2289.      * Tty-related calls:
  2290.      */
  2291.  
  2292.      case TIOCGETP: {
  2293.         struct sgttyb temp;
  2294.  
  2295.         if (debugFsStubs) {
  2296.                 printf("ioctl: TIOCGETP\n");
  2297.         }
  2298.         ioctl.command = IOC_TTY_GET_PARAMS;
  2299.         ioctl.outBufSize = sizeof(struct sgttyb);
  2300.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2301.         ioctl.outBuffer = buf;
  2302.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2303.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2304.         } else {
  2305.         ioctl.outBuffer = (Address) &temp;
  2306.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2307.         if (status == SUCCESS) {
  2308.             status = Vm_CopyOut(sizeof(struct sgttyb),
  2309.                             (Address) &temp, buf);
  2310.         }
  2311.         }
  2312.          }
  2313.      break;
  2314.  
  2315.      case TIOCSETP: {
  2316.         struct sgttyb temp;
  2317.  
  2318.         if (debugFsStubs) {
  2319.                 printf("ioctl: TIOCSETP\n");
  2320.         }
  2321.         ioctl.command = IOC_TTY_SET_PARAMS;
  2322.         ioctl.inBufSize = sizeof(struct sgttyb);
  2323.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2324.         ioctl.inBuffer = buf;
  2325.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2326.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2327.         } else {
  2328.         ioctl.inBuffer = (Address) &temp;
  2329.         status = Vm_CopyIn(sizeof(struct sgttyb), buf, (Address) &temp);
  2330.         if (status == SUCCESS) {
  2331.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2332.         }
  2333.         }
  2334.          }
  2335.      break;
  2336.  
  2337.      case TIOCSETN: {
  2338.         struct sgttyb temp;
  2339.  
  2340.         if (debugFsStubs) {
  2341.                 printf("ioctl: TIOCSETN\n");
  2342.         }
  2343.         ioctl.command = IOC_TTY_SETN;
  2344.         ioctl.inBufSize = sizeof(struct sgttyb);
  2345.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2346.         ioctl.inBuffer = buf;
  2347.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2348.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2349.         } else {
  2350.         ioctl.inBuffer = (Address) &temp;
  2351.         status = Vm_CopyIn(sizeof(struct sgttyb), buf, (Address) &temp);
  2352.         if (status == SUCCESS) {
  2353.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2354.         }
  2355.         }
  2356.          }
  2357.      break;
  2358.  
  2359.      case TIOCEXCL:
  2360.     if (debugFsStubs) {
  2361.         printf("ioctl: TIOCEXCL\n");
  2362.     }
  2363.     ioctl.command = IOC_TTY_EXCL;
  2364.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2365.     break;
  2366.  
  2367.      case TIOCNXCL:
  2368.      if (debugFsStubs) {
  2369.          printf("ioctl: TIOCNXCL\n");
  2370.      }
  2371.      ioctl.command = IOC_TTY_NXCL;
  2372.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2373.      break;
  2374.  
  2375.      case TIOCHPCL:
  2376.      if (debugFsStubs) {
  2377.          printf("ioctl: TIOCHPCL\n");
  2378.      }
  2379.      ioctl.command = IOC_TTY_HUP_ON_CLOSE;
  2380.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2381.      break;
  2382.  
  2383.      case TIOCFLUSH: {
  2384.      int temp;
  2385.  
  2386.      if (debugFsStubs) {
  2387.              printf("ioctl: TIOCFLUSH\n");
  2388.          }
  2389.      ioctl.command = IOC_TTY_NXCL;
  2390.      ioctl.inBufSize = sizeof(int);
  2391.      if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) {
  2392.          ioctl.inBuffer = buf;
  2393.          ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2394.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2395.      } else {
  2396.          ioctl.inBuffer = (Address) &temp;
  2397.          status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2398.          if (status == SUCCESS) {
  2399.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2400.          }
  2401.      }
  2402.      break;
  2403.          }
  2404.  
  2405.      case TIOCSTI: {
  2406.      int temp;
  2407.  
  2408.      if (debugFsStubs) {
  2409.          printf("ioctl: TIOCSTI\n");
  2410.      }
  2411.      ioctl.command = IOC_TTY_INSERT_CHAR;
  2412.      ioctl.inBufSize = sizeof(int);
  2413.      if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM) {
  2414.          ioctl.inBuffer = buf;
  2415.          ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2416.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2417.      } else {
  2418.          ioctl.inBuffer = (Address) &temp;
  2419.          status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2420.          if (status == SUCCESS) {
  2421.          status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2422.          }
  2423.      }
  2424.      }
  2425.      break;
  2426.  
  2427.      case TIOCSBRK:
  2428.          if (debugFsStubs) {
  2429.               printf("ioctl: TIOCSBRK\n");
  2430.          }
  2431.      ioctl.command = IOC_TTY_SET_BREAK;
  2432.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2433.      break;
  2434.  
  2435.      case TIOCCBRK:
  2436.      if (debugFsStubs) {
  2437.              printf("ioctl: TIOCCBRK\n");
  2438.          }
  2439.      ioctl.command = IOC_TTY_CLEAR_BREAK;
  2440.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2441.      break;
  2442.  
  2443.      case TIOCSDTR:
  2444.      if (debugFsStubs) {
  2445.              printf("ioctl: TIOCSDTR\n");
  2446.          }
  2447.      ioctl.command = IOC_TTY_SET_DTR;
  2448.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2449.      break;
  2450.  
  2451.      case TIOCCDTR:
  2452.      if (debugFsStubs) {
  2453.              printf("ioctl: TIOCCDTR\n");
  2454.          }
  2455.      ioctl.command = IOC_TTY_CLEAR_DTR;
  2456.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2457.      break;
  2458.  
  2459.      case TIOCGETC: {
  2460.         struct tchars temp;
  2461.  
  2462.         if (debugFsStubs) {
  2463.         printf("ioctl: TIOCGETC\n");
  2464.         }
  2465.         ioctl.command = IOC_TTY_GET_TCHARS;
  2466.         ioctl.outBufSize = sizeof(struct tchars);
  2467.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2468.         ioctl.outBuffer = buf;
  2469.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2470.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2471.         } else {
  2472.         ioctl.outBuffer = (Address) &temp;
  2473.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2474.         if (status == SUCCESS) {
  2475.             status = Vm_CopyOut(sizeof(struct tchars),
  2476.             (Address) &temp, buf);
  2477.         }
  2478.         }
  2479.          }
  2480.      break;
  2481.  
  2482.      case TIOCSETC: {
  2483.         struct tchars temp;
  2484.  
  2485.         if (debugFsStubs) {
  2486.                 printf("ioctl: TIOCSETC\n");
  2487.             }
  2488.         ioctl.command = IOC_TTY_SET_TCHARS;
  2489.         ioctl.inBufSize = sizeof(struct tchars);
  2490.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2491.         ioctl.inBuffer = buf;
  2492.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2493.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2494.         } else {
  2495.         ioctl.inBuffer = (Address) &temp;
  2496.         status = Vm_CopyIn(sizeof(struct tchars), buf, (Address) &temp);
  2497.         if (status == SUCCESS) {
  2498.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2499.         }
  2500.         }
  2501.          }
  2502.      break;
  2503.  
  2504.      case TIOCGLTC: {
  2505.         struct ltchars temp;
  2506.  
  2507.         if (debugFsStubs) {
  2508.                 printf("ioctl: TIOCGLTC\n");
  2509.             }
  2510.         ioctl.command = IOC_TTY_GET_LTCHARS;
  2511.         ioctl.outBufSize = sizeof(struct ltchars);
  2512.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2513.         ioctl.outBuffer = buf;
  2514.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2515.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2516.         } else {
  2517.         ioctl.outBuffer = (Address) &temp;
  2518.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2519.         if (status == SUCCESS) {
  2520.             status = Vm_CopyOut(sizeof(struct ltchars),
  2521.             (Address) &temp, buf);
  2522.         }
  2523.         }
  2524.          }
  2525.      break;
  2526.  
  2527.      case TIOCSLTC: {
  2528.         struct ltchars temp;
  2529.  
  2530.         if (debugFsStubs) {
  2531.                 printf("ioctl: TIOCSLTC\n");
  2532.             }
  2533.         ioctl.command = IOC_TTY_SET_LTCHARS;
  2534.         ioctl.inBufSize = sizeof(struct ltchars);
  2535.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2536.         ioctl.inBuffer = buf;
  2537.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2538.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2539.         } else {
  2540.         ioctl.inBuffer = (Address) &temp;
  2541.         status = Vm_CopyIn(sizeof(struct ltchars), buf, (Address)&temp);
  2542.         if (status == SUCCESS) {
  2543.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2544.         }
  2545.         }
  2546.         }
  2547.     break;
  2548.  
  2549.      case TIOCLBIS: {
  2550.         int temp;
  2551.  
  2552.         ioctl.command = IOC_TTY_BIS_LM;
  2553.         ioctl.inBufSize = sizeof(int);
  2554.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2555.         ioctl.inBuffer = buf;
  2556.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2557.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2558.         } else {
  2559.         ioctl.inBuffer = (Address) &temp;
  2560.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2561.         if (status == SUCCESS) {
  2562.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2563.         }
  2564.         }
  2565.          }
  2566.      break;
  2567.  
  2568.      case TIOCLBIC: {
  2569.         int temp;
  2570.  
  2571.         if (debugFsStubs) {
  2572.                 printf("ioctl: TIOCLBIC\n");
  2573.             }
  2574.         ioctl.command = IOC_TTY_BIC_LM;
  2575.         ioctl.inBufSize = sizeof(int);
  2576.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2577.         ioctl.inBuffer = buf;
  2578.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2579.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2580.         } else {
  2581.         ioctl.inBuffer = (Address) &temp;
  2582.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2583.         if (status == SUCCESS) {
  2584.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2585.         }
  2586.         }
  2587.         }
  2588.     break;
  2589.  
  2590.      case TIOCLSET: {
  2591.         int temp;
  2592.  
  2593.         if (debugFsStubs) {
  2594.                 printf("ioctl: TIOCLSET\n");
  2595.             }
  2596.         ioctl.command = IOC_TTY_SET_LM;
  2597.         ioctl.inBufSize = sizeof(int);
  2598.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2599.         ioctl.inBuffer = buf;
  2600.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2601.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2602.         } else {
  2603.         ioctl.inBuffer = (Address) &temp;
  2604.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2605.         if (status == SUCCESS) {
  2606.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2607.         }
  2608.         }
  2609.          }
  2610.      break;
  2611.  
  2612.      case TIOCLGET: {
  2613.         int temp;
  2614.  
  2615.         if (debugFsStubs) {
  2616.                 printf("ioctl: TIOCLGET\n");
  2617.             }
  2618.         ioctl.command = IOC_TTY_GET_LM;
  2619.         ioctl.outBufSize = sizeof(int);
  2620.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2621.         ioctl.outBuffer = buf;
  2622.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2623.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2624.         } else {
  2625.         ioctl.outBuffer = (Address) &temp;
  2626.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2627.         if (status == SUCCESS) {
  2628.             status = Vm_CopyOut(sizeof(int), (Address) &temp, buf);
  2629.         }
  2630.         }
  2631.          }
  2632.      break;
  2633.  
  2634.      case TIOCGETD: {
  2635.         int temp;
  2636.  
  2637.         if (debugFsStubs) {
  2638.                 printf("ioctl: TIOCGETD\n");
  2639.             }
  2640.         ioctl.command = IOC_TTY_GET_DISCIPLINE;
  2641.         ioctl.outBufSize = sizeof(int);
  2642.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2643.         ioctl.outBuffer = buf;
  2644.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2645.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2646.         } else {
  2647.         ioctl.outBuffer = (Address) &temp;
  2648.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2649.         if (status == SUCCESS) {
  2650.             status = Vm_CopyOut(sizeof(struct tchars),
  2651.             (Address) &temp, buf);
  2652.         }
  2653.         }
  2654.          }
  2655.      break;
  2656.  
  2657.      case TIOCSETD: {
  2658.         int temp;
  2659.  
  2660.         if (debugFsStubs) {
  2661.                 printf("ioctl: TIOCSETD\n");
  2662.             }
  2663.         ioctl.command = IOC_TTY_SET_DISCIPLINE;
  2664.         ioctl.inBufSize = sizeof(int);
  2665.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2666.         ioctl.inBuffer = buf;
  2667.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2668.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2669.         } else {
  2670.         ioctl.inBuffer = (Address) &temp;
  2671.         status = Vm_CopyIn(sizeof(int), buf, (Address) &temp);
  2672.         if (status == SUCCESS) {
  2673.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2674.         }
  2675.         }
  2676.         }
  2677.     break;
  2678.  
  2679.      case SIOCATMARK: {
  2680.         int temp;
  2681.  
  2682.         if (debugFsStubs) {
  2683.                 printf("ioctl: TIOCATMARK\n");
  2684.             }
  2685.         ioctl.command = IOC_NET_IS_OOB_DATA_NEXT;
  2686.         ioctl.outBufSize = sizeof(int);
  2687.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2688.         ioctl.outBuffer = buf;
  2689.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2690.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2691.         } else {
  2692.         ioctl.outBuffer = (Address) &temp;
  2693.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2694.         if (status == SUCCESS) {
  2695.             status = Vm_CopyOut(sizeof(int), (Address) &temp, buf);
  2696.         }
  2697.         }
  2698.         }
  2699.     break;
  2700.  
  2701.      case TCGETA:
  2702.      case TCGETS: {
  2703.         struct sgttyb ttyb;
  2704.         unsigned int lmode;
  2705.         struct tchars tc;
  2706.         struct ltchars ltc;
  2707.         struct termios ts;
  2708.         struct termio tio;
  2709.  
  2710.         if (debugFsStubs) {
  2711.                 printf("ioctl: TCGETS\n");
  2712.             }
  2713.  
  2714.         status = GetTermInfo(streamPtr, &ioctl, &ttyb, &lmode, &tc, <c);
  2715.         if (status == SUCCESS) {
  2716.         CvtSgttybToTermios(&ttyb, &lmode, &tc, <c, &ts);
  2717.         if (request==TCGETS) {
  2718.             status = Vm_CopyOut(sizeof(struct termios),
  2719.             (Address) &ts, buf);
  2720.         } else {
  2721.             tio.c_iflag = ts.c_iflag;
  2722.             tio.c_oflag = ts.c_oflag;
  2723.             tio.c_cflag = ts.c_cflag;
  2724.             tio.c_lflag = ts.c_lflag;
  2725.             tio.c_line = ts.c_line;
  2726.             bcopy((Address) ts.c_cc, (Address) tio.c_cc, NCC);
  2727.             status = Vm_CopyOut(sizeof(struct termio),
  2728.             (Address) &tio, buf);
  2729.         }
  2730.         }
  2731.         }
  2732.     break;
  2733.  
  2734.      case TCSETA:
  2735.      case TCSETSW:
  2736.      case TCSETSF:
  2737.      case TCSETS: {
  2738.         struct sgttyb ttyb;
  2739.         unsigned int lmode;
  2740.         struct tchars tc;
  2741.         struct ltchars ltc;
  2742.         struct termio tio;
  2743.         struct termios ts;
  2744. #define SETATYPE 0
  2745. #define SETSTYPE 1
  2746.         int type = SETSTYPE;
  2747.         if (request==TCSETA) {
  2748.         type = SETATYPE;
  2749.         }
  2750.  
  2751.         if (debugFsStubs) {
  2752.                 printf("ioctl: TCSETA/S/SW/SF\n");
  2753.             }
  2754.         status = GetTermInfo(streamPtr, &ioctl, &ttyb, &lmode, &tc, <c);
  2755.         if (status != SUCCESS) {
  2756.         Mach_SetErrno(Compat_MapCode(status));
  2757.         return -1;
  2758.         }
  2759.         if (type==SETSTYPE) {
  2760.             status = Vm_CopyIn(sizeof(struct termios),
  2761.             buf, (Address) &ts);
  2762.         } else {
  2763.             status = Vm_CopyIn(sizeof(struct termio),
  2764.             buf, (Address) &tio);
  2765.         ts.c_iflag = tio.c_iflag;
  2766.         ts.c_oflag = tio.c_oflag;
  2767.         ts.c_cflag = tio.c_cflag;
  2768.         ts.c_lflag = tio.c_lflag;
  2769.         ts.c_line = tio.c_line;
  2770.         bzero((Address) ts.c_cc, NCCS);
  2771.         bcopy((Address) tio.c_cc, (Address) ts.c_cc, NCC);
  2772.         }
  2773.         if (status == SUCCESS) {
  2774.         CvtTermiosToSgttyb((type==SETSTYPE)?1:0, &ts, &ttyb,
  2775.             &lmode, &tc, <c);
  2776.         ioctl.command = IOC_TTY_SET_PARAMS;
  2777.         ioctl.inBufSize = sizeof(struct sgttyb);
  2778.         ioctl.inBuffer = (Address) &ttyb;
  2779.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2780.         }
  2781.         if (status == SUCCESS) {
  2782.         ioctl.command = IOC_TTY_SET_LM;
  2783.         ioctl.inBufSize = sizeof(int);
  2784.         ioctl.inBuffer = (Address) &lmode;
  2785.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2786.         }
  2787.         if (status == SUCCESS) {
  2788.         ioctl.command = IOC_TTY_SET_TCHARS;
  2789.         ioctl.inBufSize = sizeof(struct tchars);
  2790.         ioctl.inBuffer = (Address) &tc;
  2791.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2792.         }
  2793.         if (status == SUCCESS) {
  2794.         ioctl.command = IOC_TTY_SET_LTCHARS;
  2795.         ioctl.inBufSize = sizeof(struct ltchars);
  2796.         ioctl.inBuffer = (Address) <c;
  2797.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2798.         }
  2799.         }
  2800.     break;
  2801.  
  2802.      case TIOCGWINSZ: {
  2803.         struct winsize temp;
  2804.  
  2805.         if (debugFsStubs) {
  2806.                 printf("ioctl: TIOCGWINSZ\n");
  2807.         }
  2808.         ioctl.command = IOC_TTY_GET_WINDOW_SIZE;
  2809.         ioctl.outBuffer = (Address) &temp;
  2810.         ioctl.outBufSize = sizeof(struct winsize);
  2811.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2812.         ioctl.outBuffer = buf;
  2813.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2814.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2815.         } else {
  2816.         ioctl.outBuffer = (Address) &temp;
  2817.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2818.         if (status == SUCCESS) {
  2819.             status = Vm_CopyOut(sizeof(struct winsize),
  2820.             (Address) &temp, buf);
  2821.         }
  2822.         }
  2823.         }
  2824.     break;
  2825.  
  2826.      case TIOCSWINSZ: {
  2827.         struct winsize temp;
  2828.  
  2829.         if (debugFsStubs) {
  2830.                 printf("ioctl: TIOCSWINSZ\n");
  2831.         }
  2832.         ioctl.command = IOC_TTY_SET_WINDOW_SIZE;
  2833.         ioctl.inBufSize = sizeof(struct winsize);
  2834.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2835.         ioctl.inBuffer = buf;
  2836.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2837.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2838.         } else {
  2839.         ioctl.inBuffer = (Address) &temp;
  2840.             status = Vm_CopyIn(sizeof(struct winsize),
  2841.             buf, (Address) &temp);
  2842.         if (status == SUCCESS) {
  2843.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2844.         }
  2845.         }
  2846.          }
  2847.      break;
  2848.  
  2849.     /*
  2850.      * Graphics requests.
  2851.      */
  2852.  
  2853.      case QIOCGINFO: {
  2854.         DevScreenInfo *temp;
  2855.  
  2856.         if (debugFsStubs) {
  2857.                 printf("ioctl: QIOCGINFO\n");
  2858.         }
  2859.         ioctl.command = IOC_GRAPHICS_GET_INFO;
  2860.         ioctl.outBufSize = sizeof(DevScreenInfo *);
  2861.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2862.         ioctl.outBuffer = buf;
  2863.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2864.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2865.         } else {
  2866.         ioctl.outBuffer = (Address) &temp;
  2867.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2868.         if (status == SUCCESS) {
  2869.             status = Vm_CopyOut(sizeof(DevScreenInfo *),
  2870.             (Address) &temp, buf);
  2871.         }
  2872.         }
  2873.         }
  2874.     break;
  2875.  
  2876.      case QIOCPMSTATE: {
  2877.         DevCursor temp;
  2878.  
  2879.         if (debugFsStubs) {
  2880.                 printf("ioctl: QIOCPMSTATE\n");
  2881.         }
  2882.         ioctl.command = IOC_GRAPHICS_MOUSE_POS;
  2883.         ioctl.outBufSize = sizeof(DevCursor);
  2884.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2885.         ioctl.outBuffer = buf;
  2886.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2887.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2888.         } else {
  2889.         ioctl.outBuffer = (Address) &temp;
  2890.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2891.         if (status == SUCCESS) {
  2892.             status = Vm_CopyOut(sizeof(DevCursor),
  2893.             (Address) &temp, buf);
  2894.         }
  2895.         }
  2896.         }
  2897.     break;
  2898.  
  2899.      case QIOWCURSORCOLOR: {
  2900.         unsigned int temp[6];
  2901.  
  2902.         if (debugFsStubs) {
  2903.                 printf("ioctl: QIOWCURSORCOLOR\n");
  2904.         }
  2905.         ioctl.command = IOC_GRAPHICS_CURSOR_COLOR;
  2906.         ioctl.inBufSize = sizeof(unsigned int [6]);
  2907.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2908.         ioctl.inBuffer = buf;
  2909.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2910.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2911.         } else {
  2912.         ioctl.inBuffer = (Address) temp;
  2913.         status = Vm_CopyIn(sizeof(unsigned int [6]),
  2914.             buf, (Address) temp);
  2915.         if (status == SUCCESS) {
  2916.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2917.         }
  2918.         }
  2919.          }
  2920.      break;
  2921.  
  2922.      case QIOCINIT:
  2923.      if (debugFsStubs) {
  2924.          printf("ioctl: QIOCINIT\n");
  2925.      }
  2926.      ioctl.command = IOC_GRAPHICS_INIT_SCREEN;
  2927.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2928.      break;
  2929.  
  2930.      case QIOCKPCMD: {
  2931.          DevKpCmd temp;
  2932.  
  2933.          if (debugFsStubs) {
  2934.                 printf("ioctl: QIOCKPCMD\n");
  2935.              }
  2936.          ioctl.command = IOC_GRAPHICS_KBD_CMD;
  2937.          ioctl.inBufSize = sizeof(DevKpCmd);
  2938.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2939.         ioctl.inBuffer = buf;
  2940.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2941.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2942.         } else {
  2943.         ioctl.inBuffer = (Address) &temp;
  2944.         status = Vm_CopyIn(sizeof(DevKpCmd), buf, (Address) &temp);
  2945.         if (status == SUCCESS) {
  2946.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2947.         }
  2948.         }
  2949.          }
  2950.      break;
  2951.  
  2952.      case QIOCADDR: {
  2953.         DevScreenInfo *temp;
  2954.  
  2955.         if (debugFsStubs) {
  2956.                 printf("ioctl: QIOCADDR\n");
  2957.             }
  2958.         ioctl.command = IOC_GRAPHICS_GET_INFO_ADDR;
  2959.         ioctl.outBufSize = sizeof(DevScreenInfo *);
  2960.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2961.         ioctl.outBuffer = buf;
  2962.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2963.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2964.         } else {
  2965.         ioctl.outBuffer = (Address) &temp;
  2966.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2967.         if (status == SUCCESS) {
  2968.             status = Vm_CopyOut(sizeof(DevScreenInfo *),
  2969.             (Address) &temp, buf);
  2970.         }
  2971.         }
  2972.         }
  2973.     break;
  2974.  
  2975.      case QIOWCURSOR: {
  2976.         short temp[32];
  2977.  
  2978.         if (debugFsStubs) {
  2979.                 printf("ioctl: QIOWCURSOR\n");
  2980.         }
  2981.         ioctl.command = IOC_GRAPHICS_CURSOR_BIT_MAP;
  2982.         ioctl.inBufSize = sizeof(short[32]);
  2983.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  2984.         ioctl.inBuffer = buf;
  2985.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  2986.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2987.         } else {
  2988.         ioctl.inBuffer = (Address) temp;
  2989.         status = Vm_CopyIn(sizeof(temp), buf, (Address) temp);
  2990.         if (status == SUCCESS) {
  2991.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  2992.         }
  2993.         }
  2994.         }
  2995.     break;
  2996.  
  2997.      case QIOKERNLOOP:
  2998.      if (debugFsStubs) {
  2999.                 printf("ioctl: QIOKERNLOOP\n");
  3000.      }
  3001.      ioctl.command = IOC_GRAPHICS_KERN_LOOP;
  3002.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3003.      break;
  3004.  
  3005.      case QIOKERNUNLOOP:
  3006.      if (debugFsStubs) {
  3007.                 printf("ioctl: QIOKERNUNLOOP\n");
  3008.      }
  3009.      ioctl.command = IOC_GRAPHICS_KERN_UNLOOP;
  3010.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3011.      break;
  3012.  
  3013.      case QIOVIDEOON:
  3014.      if (debugFsStubs) {
  3015.                 printf("ioctl: QIOVIDEOON\n");
  3016.      }
  3017.      ioctl.command = IOC_GRAPHICS_VIDEO_ON;
  3018.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3019.      break;
  3020.  
  3021.      case QIOVIDEOOFF:
  3022.      if (debugFsStubs) {
  3023.                 printf("ioctl: QIOVIDEOOFF\n");
  3024.      }
  3025.      ioctl.command = IOC_GRAPHICS_VIDEO_OFF;
  3026.      status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3027.      break;
  3028.  
  3029.      case QIOSETCMAP: {
  3030.         DevColorMap temp;
  3031.  
  3032.         if (debugFsStubs) {
  3033.                 printf("ioctl: QIOSETCMAP\n");
  3034.         }
  3035.         ioctl.command = IOC_GRAPHICS_COLOR_MAP;
  3036.         ioctl.inBufSize = sizeof(DevColorMap);
  3037.         if (streamPtr->ioHandlePtr->fileID.type == FSIO_LCL_PSEUDO_STREAM){
  3038.         ioctl.inBuffer = buf;
  3039.         ioctl.flags = FS_USER_IN|FS_USER_OUT;
  3040.         status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3041.         } else {
  3042.         ioctl.inBuffer = (Address) &temp;
  3043.         status = Vm_CopyIn(sizeof(temp), buf, (Address) &temp);
  3044.         if (status == SUCCESS) {
  3045.             status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3046.         }
  3047.         }
  3048.         }
  3049.     break;
  3050.  
  3051.       case SIOCGIFCONF: {
  3052.       /*
  3053.        * Fake the ifconfig ioctl.  This is a hack done for X.  
  3054.        * A more general implementation is probably needed.
  3055.        */
  3056.       struct ifconf ifc;
  3057.       struct ifreq   ifreq;
  3058.       extern int      sysHostID;
  3059.       int          *intPtr;
  3060.  
  3061.       if (debugFsStubs) {
  3062.                 printf("ioctl: SIOCGIFCONF\n");
  3063.       }
  3064.       status = Vm_CopyIn(sizeof(struct ifconf), buf, (Address)&ifc);
  3065.       if (status != SUCCESS) {
  3066.           return(status);
  3067.       }
  3068.  
  3069.       if (ifc.ifc_len < 32) {
  3070.           status = SYS_INVALID_ARG;
  3071.           break;
  3072.       }
  3073.       /*
  3074.        * We give a length of 32 and put in the request buffer 
  3075.        * the name ("se0"), followed by the family (AF_INET), 
  3076.        * and finally our internet address.
  3077.        */
  3078.       ifc.ifc_len = 32;
  3079.       strcpy(ifreq.ifr_name, "se0");
  3080.       intPtr = (int *)&ifreq.ifr_ifru;
  3081.       *intPtr = AF_INET;
  3082.       *(intPtr + 1) = sysHostID;
  3083.  
  3084.       status = Vm_CopyOut(sizeof(struct ifconf), (Address)&ifc, buf);
  3085.       status = Vm_CopyOut(32, (Address)&ifreq,
  3086.           (Address)ifc.ifc_ifcu.ifcu_req);
  3087.       }
  3088.       break;
  3089.  
  3090.       case SIOCRPHYSADDR: {
  3091.         /* Get the ethernet address. */
  3092.  
  3093.         struct ifdevea *p;
  3094.         Net_EtherAddress etherAddress;
  3095.  
  3096.         if (debugFsStubs) {
  3097.         printf("ioctl: SIOCRPHYSADDR\n");
  3098.         }
  3099.         Mach_GetEtherAddress(ðerAddress);
  3100.         p = (struct ifdevea *) buf;
  3101.           p->default_pa[0] = p->current_pa[0] = etherAddress.byte1;
  3102.           p->default_pa[1] = p->current_pa[1] = etherAddress.byte2;
  3103.           p->default_pa[2] = p->current_pa[2] = etherAddress.byte3;
  3104.           p->default_pa[3] = p->current_pa[3] = etherAddress.byte4;
  3105.           p->default_pa[4] = p->current_pa[4] = etherAddress.byte5;
  3106.           p->default_pa[5] = p->current_pa[5] = etherAddress.byte6;
  3107.           status = SUCCESS;
  3108.          }
  3109.      break;
  3110.  
  3111.      default:
  3112.     if (debugFsStubs) {
  3113.         /*
  3114.          * This code is for debugging, to make it easy to figure
  3115.          * out what ioctl is unimplemented.
  3116.          * It can be removed when ioctl development is reasonably
  3117.          * complete.
  3118.          */
  3119.         if ((request&IOC_DIRMASK)==IOC_VOID) {
  3120.         printf("Bad Ioctl: _IO('%c',%d)\n", (request>>8)&0xff,
  3121.             request&0xff);
  3122.         } else if ((request&IOC_DIRMASK)==IOC_OUT) {
  3123.         printf("Bad Ioctl: _IOR('%c',%d,%d)\n", (request>>8)&0xff,
  3124.             request&0xff, IOCPARM_LEN(request));
  3125.         } else if ((request&IOC_DIRMASK)==IOC_IN) {
  3126.         printf("Bad Ioctl: _IOW('%c',%d,%d)\n", (request>>8)&0xff,
  3127.             request&0xff, IOCPARM_LEN(request));
  3128.         } else if ((request&IOC_DIRMASK)==IOC_INOUT) {
  3129.         printf("Bad Ioctl: _IOWR('%c',%d,%d)\n", (request>>8)&0xff,
  3130.             request&0xff, IOCPARM_LEN(request));
  3131.         } else {
  3132.         printf("Bad Ioctl: 0x%08x\n",request);
  3133.         }
  3134.     }
  3135.     Mach_SetErrno(EINVAL);
  3136.     return -1;
  3137.     }
  3138.     if (status != SUCCESS) {
  3139.     Mach_SetErrno(Compat_MapCode(status));
  3140.     return -1;
  3141.     }        
  3142.     return 0;
  3143. }
  3144.  
  3145.  
  3146.  
  3147. /*
  3148.  *----------------------------------------------------------------------
  3149.  *
  3150.  * Fs_NewRenameStub --
  3151.  *
  3152.  *    The stub for the "newrename" Unix system call.
  3153.  *
  3154.  * Results:
  3155.  *    Returns -1 on failure.
  3156.  *
  3157.  * Side effects:
  3158.  *    Side effects associated with the system call.
  3159.  *     
  3160.  *
  3161.  *----------------------------------------------------------------------
  3162.  */
  3163. int
  3164. Fs_NewRenameStub(pathName, newName)
  3165.     char *pathName;
  3166.     char *newName;
  3167. {
  3168.     ReturnStatus    status;
  3169.     int            pathNameLength;
  3170.     int            newNameLength;
  3171.     char        newPathName[FS_MAX_PATH_NAME_LENGTH];
  3172.     char        *newNewName;
  3173.  
  3174.     if (debugFsStubs) {
  3175.     printf("Fs_RenameStub\n");
  3176.     }
  3177.     /*
  3178.      * Copy the name in from user space onto the kernel stack.
  3179.      */
  3180.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newPathName,
  3181.                &pathNameLength) != SUCCESS) {
  3182.     Mach_SetErrno(EACCES);
  3183.     return -1;
  3184.     }
  3185.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3186.     Mach_SetErrno(EINVAL);
  3187.     return -1;
  3188.     }
  3189.  
  3190.     /*
  3191.      * Maybe I could put the new name onto the stack as well but I am 
  3192.      * allocing it here because I'm not sure if the stack is big enough.
  3193.      * Should just make the stack bigger I suppose ...
  3194.      */
  3195.     newNewName = (char  *) malloc(FS_MAX_PATH_NAME_LENGTH);
  3196.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, newName, newNewName,
  3197.                &newNameLength) == SUCCESS) {
  3198.     if (newNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3199.         status = FS_INVALID_ARG;
  3200.     } else {
  3201.         status = Fs_Rename(newPathName, newNewName);
  3202.     }
  3203.     } else {
  3204.     status = SYS_ARG_NOACCESS;
  3205.     }
  3206.     free((Address) newNewName);
  3207.     if (status != SUCCESS) {
  3208.     Mach_SetErrno(Compat_MapCode(status));
  3209.     return -1;
  3210.     }
  3211.     return 0;
  3212. }
  3213.  
  3214.  
  3215. /*
  3216.  *----------------------------------------------------------------------
  3217.  *
  3218.  * Fs_FtruncateStub --
  3219.  *
  3220.  *    The stub for the "ftruncate" Unix system call.
  3221.  *
  3222.  * Results:
  3223.  *    Returns -1 on failure.
  3224.  *
  3225.  * Side effects:
  3226.  *    Side effects associated with the system call.
  3227.  *     
  3228.  *
  3229.  *----------------------------------------------------------------------
  3230.  */
  3231. int
  3232. Fs_FtruncateStub(streamID, length)
  3233.     int streamID;
  3234.     unsigned long length;
  3235. {
  3236.     ReturnStatus        status;
  3237.     Proc_ControlBlock   *procPtr;
  3238.     Fs_Stream             *streamPtr;
  3239.     Fs_IOCParam         ioctl;
  3240.     Fs_IOReply          reply;
  3241.  
  3242.     if (debugFsStubs) {
  3243.     printf("Fs_FtruncateStub\n");
  3244.     }
  3245.     procPtr = Proc_GetEffectiveProc();
  3246.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  3247.     ioctl.command = IOC_TRUNCATE;
  3248.     ioctl.format = mach_Format;
  3249.     ioctl.procID = procPtr->processID;
  3250.     ioctl.familyID = procPtr->familyID;
  3251.     ioctl.uid = procPtr->effectiveUserID;
  3252.     ioctl.flags = 0;
  3253.     ioctl.outBuffer = 0;
  3254.     ioctl.outBufSize = 0;
  3255.     ioctl.inBuffer = (Address) &length;
  3256.     ioctl.inBufSize = sizeof(length);
  3257.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3258.     if (status != SUCCESS) {
  3259.     Mach_SetErrno(Compat_MapCode(status));
  3260.     return -1;
  3261.     }
  3262.     return 0;
  3263. }
  3264.  
  3265. /*
  3266.  *----------------------------------------------------------------------
  3267.  *
  3268.  * Fs_TruncateStub --
  3269.  *
  3270.  *    The stub for the "truncate" Unix system call.
  3271.  *
  3272.  * Results:
  3273.  *    Returns -1 on failure.
  3274.  *
  3275.  * Side effects:
  3276.  *    Side effects associated with the system call.
  3277.  *     
  3278.  *
  3279.  *----------------------------------------------------------------------
  3280.  */
  3281. int
  3282. Fs_TruncateStub(path, length)
  3283.     char *path;
  3284.     unsigned long length;
  3285. {
  3286.     int    streamID;
  3287.     int status;
  3288.  
  3289.     if (debugFsStubs) {
  3290.     printf("Fs_TruncateStub\n");
  3291.     }
  3292.     streamID = Fs_NewOpenStub(path, FS_WRITE, 0);
  3293.     if (streamID == -1) {
  3294.     return -1;
  3295.     }
  3296.     status = Fs_FtruncateStub(streamID, length);
  3297.     (void) Fs_UserClose(streamID);
  3298.     return status;
  3299. }
  3300.  
  3301. /*
  3302.  *----------------------------------------------------------------------
  3303.  *
  3304.  * Fs_FlockStub --
  3305.  *
  3306.  *    The stub for the "flock" Unix system call.
  3307.  *
  3308.  * Results:
  3309.  *    Returns -1 on failure.
  3310.  *
  3311.  * Side effects:
  3312.  *    Side effects associated with the system call.
  3313.  *     
  3314.  *
  3315.  *----------------------------------------------------------------------
  3316.  */
  3317. int
  3318. Fs_FlockStub(streamID, operation)
  3319.     int    streamID;
  3320.     int operation;
  3321. {
  3322.     ReturnStatus status;
  3323.     Ioc_LockArgs args;
  3324.     Proc_ControlBlock   *procPtr;
  3325.     Fs_Stream             *streamPtr;
  3326.     Fs_IOCParam         ioctl;
  3327.     Fs_IOReply          reply;
  3328.  
  3329.     if (debugFsStubs) {
  3330.     printf("Fs_FlockStub\n");
  3331.     }
  3332.     args.flags = 0;
  3333.     if (operation & LOCK_EX) {
  3334.     args.flags |= IOC_LOCK_EXCLUSIVE;
  3335.     } else if (operation & LOCK_SH) {
  3336.     args.flags |= IOC_LOCK_SHARED;
  3337.     }
  3338.     if (operation & LOCK_NB) {
  3339.     args.flags |= IOC_LOCK_NO_BLOCK;
  3340.     }
  3341.     procPtr = Proc_GetEffectiveProc();
  3342.     status = Fs_GetStreamPtr(procPtr, streamID, &streamPtr);
  3343.     if (operation & LOCK_UN) {
  3344.     ioctl.command = IOC_UNLOCK;
  3345.     } else {
  3346.     ioctl.command = IOC_LOCK;
  3347.     }
  3348.     ioctl.format = mach_Format;
  3349.     ioctl.procID = procPtr->processID;
  3350.     ioctl.familyID = procPtr->familyID;
  3351.     ioctl.uid = procPtr->effectiveUserID;
  3352.     ioctl.flags = 0;
  3353.     ioctl.outBuffer = 0;
  3354.     ioctl.outBufSize = 0;
  3355.     ioctl.inBuffer = (Address) &args;
  3356.     ioctl.inBufSize = sizeof(Ioc_LockArgs),
  3357.     status = Fs_IOControl(streamPtr, &ioctl, &reply);
  3358.     if (status != SUCCESS) {
  3359.     Mach_SetErrno(Compat_MapCode(status));
  3360.     return -1;
  3361.     }
  3362.     return 0;
  3363. }
  3364.  
  3365.  
  3366. /*
  3367.  *----------------------------------------------------------------------
  3368.  *
  3369.  * Fs_MkdirStub --
  3370.  *
  3371.  *    The stub for the "mkdir" Unix system call.
  3372.  *
  3373.  * Results:
  3374.  *    Returns -1 on failure.
  3375.  *
  3376.  * Side effects:
  3377.  *    Side effects associated with the system call.
  3378.  *     
  3379.  *
  3380.  *----------------------------------------------------------------------
  3381.  */
  3382. int
  3383. Fs_MkdirStub(pathName, permissions)
  3384.     char *pathName;        /* The name of the directory to create */
  3385.     int permissions;        /* Permission mask to use on creation */
  3386. {
  3387.     ReturnStatus        status;
  3388.     int            pathNameLength;
  3389.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  3390.  
  3391.     if (debugFsStubs) {
  3392.     printf("Fs_MkdirStub\n");
  3393.     }
  3394.     /*
  3395.      * Copy the name in from user space to the kernel stack.
  3396.      */
  3397.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  3398.                &pathNameLength) != SUCCESS) {
  3399.     Mach_SetErrno(EACCES);
  3400.     return -1;
  3401.     }
  3402.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3403.     Mach_SetErrno(EINVAL);
  3404.     return -1;
  3405.     }
  3406.     status = Fs_MakeDir(newName, permissions);
  3407.     if (status != SUCCESS) {
  3408.     Mach_SetErrno(Compat_MapCode(status));
  3409.     return -1;
  3410.     }
  3411.     return 0;
  3412. }
  3413.  
  3414. /*
  3415.  *----------------------------------------------------------------------
  3416.  *
  3417.  * Fs_RmdirStub --
  3418.  *
  3419.  *    The stub for the "rmdir" Unix system call.
  3420.  *
  3421.  * Results:
  3422.  *    Returns -1 on failure.
  3423.  *
  3424.  * Side effects:
  3425.  *    Side effects associated with the system call.
  3426.  *     
  3427.  *
  3428.  *----------------------------------------------------------------------
  3429.  */
  3430. int
  3431. Fs_RmdirStub(pathName)
  3432.     char *pathName;        /* The name of the directory to create */
  3433. {
  3434.     ReturnStatus    status;
  3435.     int            pathNameLength;
  3436.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  3437.  
  3438.     if (debugFsStubs) {
  3439.     printf("Fs_RmdirStub\n");
  3440.     }
  3441.     /*
  3442.      * Copy the name in from user space onto the kernel stack.
  3443.      */
  3444.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  3445.                &pathNameLength) != SUCCESS) {
  3446.     Mach_SetErrno(EACCES);
  3447.     return -1;
  3448.     }
  3449.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3450.     Mach_SetErrno(EINVAL);
  3451.     return -1;
  3452.     }
  3453.     status = Fs_RemoveDir(newName);
  3454.     if (status != SUCCESS) {
  3455.     Mach_SetErrno(Compat_MapCode(status));
  3456.     return -1;
  3457.     }
  3458.     return 0;
  3459. }
  3460.  
  3461. /*
  3462.  *----------------------------------------------------------------------
  3463.  *
  3464.  * Fs_UtimesStub --
  3465.  *
  3466.  *    The stub for the "utimes" Unix system call.
  3467.  *
  3468.  * Results:
  3469.  *    Returns -1 on failure.
  3470.  *
  3471.  * Side effects:
  3472.  *    Side effects associated with the system call.
  3473.  *     
  3474.  *
  3475.  *----------------------------------------------------------------------
  3476.  */
  3477. int
  3478. Fs_UtimesStub(pathName, tvp)
  3479.     char    *pathName;
  3480.     struct timeval *tvp;
  3481. {
  3482.     ReturnStatus    status;
  3483.     Fs_Attributes   attributes;
  3484.     int            pathNameLength;
  3485.     char        newName[FS_MAX_PATH_NAME_LENGTH];
  3486.     struct timeval  tv[2];
  3487.  
  3488.     if (debugFsStubs) {
  3489.     printf("Fs_Utimes\n");
  3490.     }
  3491.  
  3492.     if (Vm_CopyIn(sizeof(tv), (Address) tvp, (Address) tv) != SUCCESS) {
  3493.     Mach_SetErrno(EFAULT);
  3494.     return -1;
  3495.     }
  3496.     attributes.accessTime.seconds = tv[0].tv_sec;
  3497.     attributes.accessTime.microseconds = tv[0].tv_usec;
  3498.     attributes.dataModifyTime.seconds = tv[1].tv_sec;
  3499.     attributes.dataModifyTime.microseconds = tv[1].tv_usec;
  3500.  
  3501.     /*
  3502.      * Copy the name in from user space onto the kernel stack.
  3503.      */
  3504.     if (Fsutil_StringNCopy(FS_MAX_PATH_NAME_LENGTH, pathName, newName,
  3505.                &pathNameLength) != SUCCESS) {
  3506.         Mach_SetErrno(EACCES);
  3507.     return -1;
  3508.     }
  3509.     if (pathNameLength == FS_MAX_PATH_NAME_LENGTH) {
  3510.     Mach_SetErrno(EINVAL);
  3511.     return -1;
  3512.     }
  3513.     status = Fs_SetAttributes(newName,
  3514.                           FS_ATTRIB_FILE, &attributes, FS_SET_TIMES);
  3515.     if (status != SUCCESS) {
  3516.     Mach_SetErrno(Compat_MapCode(status));
  3517.     return -1;
  3518.     }
  3519.     return 0;
  3520. }
  3521.  
  3522. /*
  3523.  *----------------------------------------------------------------------
  3524.  *
  3525.  * Fs_SyncStub --
  3526.  *
  3527.  *    The stub for the "sync" Unix system call.
  3528.  *
  3529.  * Results:
  3530.  *    Returns -1 on failure.
  3531.  *
  3532.  * Side effects:
  3533.  *    Side effects associated with the system call.
  3534.  *     
  3535.  *
  3536.  *----------------------------------------------------------------------
  3537.  */
  3538. int
  3539. Fs_SyncStub()
  3540. {
  3541.  
  3542.     printf("Fs_SyncStub is not implemented\n");
  3543.     Mach_SetErrno(EINVAL);
  3544.     return -1;
  3545. }
  3546.  
  3547. /*
  3548.  *----------------------------------------------------------------------
  3549.  *
  3550.  * Fs_GetdtablesizeStub --
  3551.  *
  3552.  *    The stub for the "getdtablesize" Unix system call.
  3553.  *
  3554.  * Results:
  3555.  *    Returns -1 on failure.
  3556.  *
  3557.  * Side effects:
  3558.  *    Side effects associated with the system call.
  3559.  *     
  3560.  *
  3561.  *----------------------------------------------------------------------
  3562.  */
  3563. int 
  3564. Fs_GetdtablesizeStub()
  3565. {
  3566.  
  3567.     if (debugFsStubs) {
  3568.     printf("Fs_GetdtablesizeStub\n");
  3569.     }
  3570.     return 100;
  3571. }
  3572.  
  3573. /*
  3574.  *----------------------------------------------------------------------
  3575.  *
  3576.  * Fs_GetdoptStub --
  3577.  *
  3578.  *    The stub for the "getdopt" Unix system call.
  3579.  *
  3580.  * Results:
  3581.  *    Returns -1 on failure.
  3582.  *
  3583.  * Side effects:
  3584.  *    Side effects associated with the system call.
  3585.  *     
  3586.  *
  3587.  *----------------------------------------------------------------------
  3588.  */
  3589. int
  3590. Fs_GetdoptStub()
  3591.  
  3592. {
  3593.  
  3594.     printf("getdopt is not implemented\n");
  3595.     Mach_SetErrno(EINVAL);
  3596.     return -1;
  3597. }
  3598.  
  3599. /*
  3600.  *----------------------------------------------------------------------
  3601.  *
  3602.  * Fs_SetdoptStub --
  3603.  *
  3604.  *    The stub for the "setdopt" Unix system call.
  3605.  *
  3606.  * Results:
  3607.  *    Returns -1 on failure.
  3608.  *
  3609.  * Side effects:
  3610.  *    Side effects associated with the system call.
  3611.  *     
  3612.  *
  3613.  *----------------------------------------------------------------------
  3614.  */
  3615. int
  3616. Fs_SetdoptStub()
  3617. {
  3618.  
  3619.     printf("setdopt is not implemented\n");
  3620.     Mach_SetErrno(EINVAL);
  3621.     return -1;
  3622. }
  3623.  
  3624. /*
  3625.  *----------------------------------------------------------------------
  3626.  *
  3627.  * Fs_FcntlStub --
  3628.  *
  3629.  *    The stub for the "fcntl" Unix system call.
  3630.  *
  3631.  * Results:
  3632.  *    Returns -1 on failure.
  3633.  *
  3634.  * Side effects:
  3635.  *    Side effects associated with the system call.
  3636.  *     
  3637.  *
  3638.  *----------------------------------------------------------------------
  3639.  */
  3640. int
  3641. Fs_FcntlStub(fd, cmd, arg)
  3642. int fd, cmd, arg;
  3643. {
  3644.  
  3645.     Proc_ControlBlock *procPtr=Proc_GetEffectiveProc();
  3646.     Fs_Stream *streamPtr;
  3647.     ReturnStatus status;
  3648.     int value;
  3649.     Address        usp;
  3650.  
  3651.     if (debugFsStubs) {
  3652.     printf("Fs_FcntlStub(%d, %d, %d)\n", fd, cmd, arg);
  3653.     }
  3654.  
  3655.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  3656.     if (status != SUCCESS) {
  3657.     Mach_SetErrno(EBADF);
  3658.     return -1;
  3659.     }
  3660.  
  3661.     usp = Mach_UserStack();
  3662.  
  3663.     switch (cmd) {
  3664.     case F_DUPFD:
  3665.         value = arg;
  3666.         status = Fs_GetNewID(fd, (int *)&value);
  3667.         if (status == SUCCESS) {
  3668.         return value;
  3669.         }
  3670.         break;
  3671.  
  3672.     case F_GETFD:
  3673.         usp -= sizeof(int);
  3674.         status = Fs_IOControlStub(fd, IOC_GET_FLAGS, 
  3675.                 0, (Address) NULL, sizeof(value), usp);
  3676.         if (status == SUCCESS) {
  3677.         (void)Vm_CopyIn(sizeof(int), (Address)usp, (Address)value);
  3678.         return (value & IOC_CLOSE_ON_EXEC) ? 1 : 0;
  3679.         }
  3680.         break;
  3681.  
  3682.     case F_SETFD:
  3683.         usp -= sizeof(int);
  3684.         value = IOC_CLOSE_ON_EXEC;
  3685.         status = Vm_CopyOut(sizeof(value), (Address)&value, usp);
  3686.         if (status != SUCCESS) {
  3687.         break;
  3688.         }
  3689.         if (arg & 1) {
  3690.         status = Fs_IOControlStub(fd, IOC_SET_BITS, 
  3691.                 sizeof(value), usp, 0, (Address) NULL);
  3692.         } else {
  3693.         status = Fs_IOControlStub(fd, IOC_CLEAR_BITS, 
  3694.                 sizeof(value), usp, 0, (Address) NULL);
  3695.         }
  3696.         if (status == SUCCESS) {
  3697.         return 0;
  3698.         }
  3699.         break;
  3700.  
  3701.     case F_GETFL:  {
  3702.         int temp, returnValue;
  3703.  
  3704.         usp -= sizeof(int);
  3705.         status = Fs_IOControlStub(fd, IOC_GET_FLAGS, 
  3706.                 0, (Address) NULL, sizeof(temp), usp);
  3707.         if (status != SUCCESS) {
  3708.             break;
  3709.         }
  3710.  
  3711.         returnValue = 0;
  3712.  
  3713.         (void)Vm_CopyIn(sizeof(temp), usp, (Address)&temp);
  3714.         if (temp & IOC_APPEND) {
  3715.             returnValue |= FAPPEND;
  3716.         }
  3717.         if (temp & IOC_NON_BLOCKING) {
  3718.             returnValue |= FNDELAY;
  3719.         }
  3720.         if (temp & IOC_ASYNCHRONOUS) {
  3721.             returnValue |= FASYNC;
  3722.         }
  3723.         return returnValue;
  3724.         }
  3725.         break;
  3726.  
  3727.     case F_SETFL:
  3728.         value = 0;
  3729.         if (arg & FAPPEND) {
  3730.         value |= IOC_APPEND;
  3731.         }
  3732.         if (arg & FNDELAY) {
  3733.         value |= IOC_NON_BLOCKING;
  3734.         }
  3735.         if (arg & FASYNC) {
  3736.         value |= IOC_ASYNCHRONOUS;
  3737.         }
  3738.         if (value == 0) {
  3739.         status = SUCCESS;
  3740.         } else {
  3741.         usp -= sizeof(int);
  3742.         status = Vm_CopyOut(sizeof(value), (Address)&value, usp);
  3743.         if (status != SUCCESS) {
  3744.             break;
  3745.         }
  3746.         status = Fs_IOControlStub(fd, IOC_SET_BITS, 
  3747.                 sizeof(value), usp, 0, (Address) NULL);
  3748.         }
  3749.         if (status == SUCCESS) {
  3750.         return 0;
  3751.         }
  3752.         break;
  3753.  
  3754.     case F_GETOWN: {
  3755.         Ioc_Owner owner;
  3756.  
  3757.         usp -= sizeof(owner);
  3758.         status = Fs_IOControlStub(fd, IOC_GET_OWNER, 
  3759.                       0, (Address) NULL,
  3760.                       sizeof(owner), usp);
  3761.         if (status != SUCCESS) {
  3762.             break;
  3763.         }
  3764.         (void)Vm_CopyIn(sizeof(owner), (Address)usp, (Address)&owner);
  3765.         if (owner.procOrFamily == IOC_OWNER_FAMILY) {
  3766.             return -owner.id;
  3767.         } else {
  3768.             return owner.id;
  3769.         }
  3770.         }
  3771.         break;
  3772.  
  3773.     case F_SETOWN: {
  3774.         Ioc_Owner owner;
  3775.  
  3776.         usp -= sizeof(owner);
  3777.         if (arg < 0) {
  3778.             owner.id = -arg;
  3779.             owner.procOrFamily = IOC_OWNER_FAMILY;
  3780.         } else {
  3781.             owner.id = arg;
  3782.             owner.procOrFamily = IOC_OWNER_PROC;
  3783.         }
  3784.         status = Vm_CopyOut(sizeof(owner), (Address)&owner, usp);
  3785.         if (status != SUCCESS) {
  3786.             break;
  3787.         }
  3788.         status = Fs_IOControlStub(fd, IOC_SET_OWNER, 
  3789.                 sizeof(owner), usp, 0, (Address) NULL);
  3790.         if (status == SUCCESS) {
  3791.             return 0;
  3792.         }
  3793.             
  3794.         }
  3795.         break;
  3796.  
  3797.     default:
  3798.         printf("Unimplemented fcntl function %d\n", cmd);
  3799.         Mach_SetErrno(EINVAL);
  3800.         return -1;
  3801.         break;
  3802.     }
  3803.  
  3804.     Mach_SetErrno(Compat_MapCode(status));
  3805.     return -1;
  3806. }
  3807.  
  3808. #define DIR_BUF 4096
  3809.  
  3810. /*
  3811.  *----------------------------------------------------------------------
  3812.  *
  3813.  * Fs_GetdirInt --
  3814.  *
  3815.  *    This is an internal routine to get some directory entries.
  3816.  *    It does the byteswapping on the buffer.
  3817.  *    A partial record won't be byteswapped.
  3818.  *    It will read the requested number of bytes if they exist.
  3819.  *    The file pointer will point to the end of the data read.
  3820.  *
  3821.  * Results:
  3822.  *    Returns number of bytes read if successful.
  3823.  *    Returns -1 if error.
  3824.  *
  3825.  * Side effects:
  3826.  *    Reads from the file.
  3827.  *    Puts return value in variables.
  3828.  *
  3829.  *----------------------------------------------------------------------
  3830.  */
  3831. /*ARGSUSED*/
  3832. static int
  3833. Fs_GetdirInt(fd, nbytes, buf, off)
  3834.     int            fd;
  3835.     int            nbytes;    /* Length of user buffer. */
  3836.     Address        buf;    /* Kernel space buffer for data. */
  3837.     long        *off;    /* File offset at start */
  3838. {
  3839.     ReturnStatus     status;    /* result returned by Fs_Read */
  3840.     int            i;
  3841.     int            offset;
  3842.     Proc_ControlBlock    *procPtr;
  3843.     Fs_Stream        *streamPtr;
  3844.     int            bytesRead;
  3845.     Fs_Attributes    spriteAttrs;
  3846.     Fslcl_DirEntry    *dirPtr;
  3847.  
  3848.     if (debugFsStubs) {
  3849.     printf("Fs_GetdirInt(%d, %d, %x)\n", fd, nbytes, buf);
  3850.     }
  3851.     if (nbytes < sizeof(struct direct)) {
  3852.     Mach_SetErrno(EINVAL);
  3853.     return -1;
  3854.     }
  3855.     procPtr = Proc_GetEffectiveProc();
  3856.     status = Fs_GetStreamPtr(procPtr, fd, &streamPtr);
  3857.     if (status == SUCCESS) {
  3858.     status = Fs_GetAttrStream(streamPtr, &spriteAttrs);
  3859.     }
  3860.     if (status != SUCCESS) {
  3861.     Mach_SetErrno(EBADF);
  3862.     return -1;
  3863.     }
  3864.     if (spriteAttrs.type != FS_DIRECTORY) {
  3865.     Mach_SetErrno(ENOTDIR);
  3866.     return -1;
  3867.     }
  3868.  
  3869.     offset = streamPtr->offset;
  3870.     *off = offset;
  3871.     bytesRead = nbytes;
  3872.     if (debugFsStubs) {
  3873.     printf("Doing Fs_Read: %x, %x, %x, %x\n", streamPtr, buf, offset,
  3874.         bytesRead);
  3875.     }
  3876.     streamPtr->flags &= ~FS_USER;
  3877.     status = Fs_Read(streamPtr, buf, offset, &bytesRead);
  3878.     streamPtr->flags |= FS_USER;
  3879.     if (status != SUCCESS) {
  3880.     if (debugFsStubs) {
  3881.         printf("Read: status %x\n", status);
  3882.     }
  3883.     Mach_SetErrno(Compat_MapCode(status));
  3884.     return -1;
  3885.     }
  3886.  
  3887.     /*
  3888.      * Check against big-endian/little-endian conflict.
  3889.      * The max record length is 512, which is 02 when byteswapped.
  3890.      * The min record length is 8, which is > 512 when byteswapped.
  3891.      * All other values fall outside the range 8-512 when byteswapped.
  3892.      */
  3893.     dirPtr = (Fslcl_DirEntry *)buf;
  3894.     if (debugFsStubs) {
  3895.     printf("Fs_GetdirInt: recordLength = %d\n", dirPtr->recordLength);
  3896.     }
  3897.     if (dirPtr->recordLength > FSLCL_DIR_BLOCK_SIZE ||
  3898.     dirPtr->recordLength < 2 * (int)sizeof(int)) {
  3899.     if (debugFsStubs) {
  3900.         printf("Fs_GetdirInt: swapping entries\n");
  3901.         printf("Bytes: %x %x %x %x\n", ((int *)buf)[0], ((int *)buf)[1],
  3902.         ((int *)buf)[2], ((int *)buf)[3]);
  3903.     }
  3904.     i = bytesRead;
  3905.     while (i >= (int)(sizeof(u_long)+2*sizeof(u_short))) {
  3906.         union {
  3907.         short    s;
  3908.         char    c[2];
  3909.         } shortIn, shortOut;
  3910.         union {
  3911.         int    i;
  3912.         char    c[4];
  3913.         } intIn, intOut;
  3914.  
  3915.         intIn.i = dirPtr->fileNumber;
  3916.         intOut.c[0] = intIn.c[3];
  3917.         intOut.c[1] = intIn.c[2];
  3918.         intOut.c[2] = intIn.c[1];
  3919.         intOut.c[3] = intIn.c[0];
  3920.         dirPtr->fileNumber = intOut.i;
  3921.  
  3922.         shortIn.s = dirPtr->recordLength;
  3923.         shortOut.c[0] = shortIn.c[1];
  3924.         shortOut.c[1] = shortIn.c[0];
  3925.         dirPtr->recordLength = shortOut.s;
  3926.  
  3927.         shortIn.s = dirPtr->nameLength;
  3928.         shortOut.c[0] = shortIn.c[1];
  3929.         shortOut.c[1] = shortIn.c[0];
  3930.         dirPtr->nameLength = shortOut.s;
  3931.  
  3932.         if (dirPtr->recordLength <= 0) {
  3933.         printf("Fs_GetdirInt: length = %d!!\n", dirPtr->recordLength);
  3934.         return -1;
  3935.         }
  3936.         i -= dirPtr->recordLength;
  3937.         dirPtr = (Fslcl_DirEntry *) ((Address)dirPtr +
  3938.             dirPtr->recordLength);
  3939.     }
  3940.     }
  3941.     return bytesRead;
  3942. }
  3943.  
  3944. /*
  3945.  *----------------------------------------------------------------------
  3946.  *
  3947.  * Fs_GetdentsStub --
  3948.  *
  3949.  *    The stub for the "getdents" Unix system call.
  3950.  *
  3951.  * Results:
  3952.  *    Returns -1 on failure.
  3953.  *
  3954.  * Side effects:
  3955.  *    Side effects associated with the system call.
  3956.  *     
  3957.  *
  3958.  *----------------------------------------------------------------------
  3959.  */
  3960. int
  3961. Fs_GetdentsStub(fd, buf, nbytes)
  3962.     int  fd;
  3963.     char *buf;
  3964.     int nbytes;
  3965. {
  3966.     ReturnStatus     status;
  3967.     int            bytesRead;
  3968.     int            bytesStored, bytesUsed;
  3969.     char        kBuf[DIR_BUF];
  3970.     char        kBuf2[DIR_BUF];
  3971.     Address        directPtr, directPtr2;
  3972.     long        offset;
  3973.     int            dirsiz;
  3974.  
  3975.     if (debugFsStubs) {
  3976.     printf("Fs_Getdents(%d, %x, %d)\n", fd, buf, nbytes);
  3977.     }
  3978.     assert(sizeof(struct dirent) == sizeof(struct direct)+4);
  3979.  
  3980.     if (nbytes<sizeof(struct dirent)) {
  3981.     Mach_SetErrno(EINVAL);
  3982.     return -1;
  3983.     }
  3984.  
  3985.     if (nbytes>DIR_BUF) {
  3986.     nbytes = DIR_BUF;
  3987.     }
  3988.  
  3989.     bytesStored = 0;
  3990.     while (bytesStored==0) {
  3991.     bytesRead = Fs_GetdirInt(fd, nbytes, kBuf, &offset);
  3992.     bytesUsed = 0;
  3993.     if (debugFsStubs) {
  3994.         printf("Fs_Getdirentries got %d bytes from Fs_GetdirInt\n",
  3995.             bytesRead);
  3996.     }
  3997.     if (bytesRead <=0) {
  3998.         return bytesRead;
  3999.     }
  4000.  
  4001.     /*
  4002.      * Scan through the entries converting them to the new format.
  4003.      * directPtr points to the directory we read in.
  4004.      * directPtr2 points to the directory we are creating.
  4005.      * We can take bytesRead bytes from directPtr, and we count these
  4006.      * in bytesUsed.
  4007.      * We can put nbytes bytes into directPtr2, and we count these
  4008.      * in bytesStored.
  4009.      */
  4010.  
  4011.     directPtr = kBuf;
  4012.     directPtr2 = kBuf2;
  4013.  
  4014.     while (bytesUsed+sizeof(u_long)+2*sizeof(u_short) <= bytesRead &&
  4015.         bytesStored < nbytes) {
  4016.         dirsiz = DIRSIZ((struct direct *)directPtr);
  4017.         if (debugFsStubs) {
  4018.         printf("dirsiz = %d\n", dirsiz);
  4019.         printf("bytes = %x %x %x\n", ((int *)directPtr)[0],
  4020.             ((int *)directPtr)[1], ((int *)directPtr)[2]);
  4021.         printf("d_reclen %d, d_namlen %d\n", ((struct direct *)
  4022.             directPtr)->d_reclen,
  4023.             ((struct direct *)directPtr)->d_namlen);
  4024.         }
  4025.         if (dirsiz > sizeof(struct direct) || ((struct direct *)
  4026.             directPtr)->d_reclen > FSLCL_DIR_BLOCK_SIZE) {
  4027.         printf("Fs_Getdirentries: Directory record too long!\n");
  4028.         printf("dirsiz = %d, reclen = %d\n", dirsiz,
  4029.             ((struct direct *)directPtr)->d_reclen);
  4030.         Mach_SetErrno(EINVAL);
  4031.         return -1;
  4032.         }
  4033.         if (((struct direct *)directPtr)->d_ino != 0) {
  4034.         if (bytesUsed+dirsiz>bytesRead ||
  4035.             bytesStored+dirsiz+sizeof(off_t)>nbytes){
  4036.             break;
  4037.         }
  4038.         bcopy(directPtr, directPtr2+sizeof(off_t), dirsiz);
  4039.         ((struct dirent *)directPtr2)->d_off = offset+bytesUsed;
  4040.         ((struct dirent *)directPtr2)->d_reclen = dirsiz+sizeof(off_t);
  4041.         bytesStored += dirsiz+sizeof(off_t);
  4042.         directPtr2 += dirsiz+sizeof(off_t);
  4043.         }
  4044.         bytesUsed += ((struct direct *)directPtr)->d_reclen;
  4045.         directPtr += ((struct direct *)directPtr)->d_reclen;
  4046.         if (bytesStored > nbytes) {
  4047.         printf("Overflow! %d vs %d, %d vs %d\n", bytesUsed, bytesRead,
  4048.             bytesStored, nbytes);
  4049.         Mach_SetErrno(EINVAL);
  4050.         return -1;
  4051.         }
  4052.     }
  4053.  
  4054.     /*
  4055.      * Set the file pointer.
  4056.      */
  4057.     if (bytesUsed != bytesRead) {
  4058.         if (debugFsStubs) {
  4059.         printf("old offset = %d, read %d, used %d\n",
  4060.             offset, bytesRead, bytesUsed);
  4061.         }
  4062.         status = Fs_LseekStub(fd, offset+bytesUsed, L_SET);
  4063.         if (status < 0) {
  4064.         printf("Lseek to %d failed in getdents!\n", offset+bytesUsed);
  4065.         return -1;
  4066.         }
  4067.     }
  4068.     }
  4069.  
  4070.     /*
  4071.      * Copy out the results.
  4072.      */
  4073.  
  4074.     status = Vm_CopyOut(bytesStored, kBuf2, buf);
  4075.     if (status != SUCCESS) {
  4076.     Mach_SetErrno(EFAULT);
  4077.     return -1;
  4078.     }
  4079.  
  4080.     return bytesStored;
  4081. }
  4082. /*
  4083.  *----------------------------------------------------------------------
  4084.  *
  4085.  * Fs_GetdirentriesStub --
  4086.  *
  4087.  *    The stub for the "getdirentries" Unix system call.
  4088.  *
  4089.  * Results:
  4090.  *    Returns -1 on failure.
  4091.  *
  4092.  * Side effects:
  4093.  *    Side effects associated with the system call.
  4094.  *     
  4095.  *
  4096.  *----------------------------------------------------------------------
  4097.  */
  4098. int 
  4099. Fs_GetdirentriesStub(fd, buf, nbytes, basep)
  4100.     int  fd;
  4101.     char *buf;
  4102.     int nbytes;
  4103.     long *basep;
  4104.  
  4105. {
  4106.     ReturnStatus     status;
  4107.     int            bytesRead;
  4108.     int            bytesStored, bytesUsed;
  4109.     char        kBuf[DIR_BUF];
  4110.     char        kBuf2[DIR_BUF];
  4111.     Address        directPtr, directPtr2;
  4112.     long        offset;
  4113.     int            dirsiz;
  4114.  
  4115.     if (debugFsStubs) {
  4116.     printf("Fs_Getdirentries(%d, %x, %d, %x)\n", fd, buf, nbytes, basep);
  4117.     }
  4118.  
  4119.     if (nbytes > DIR_BUF) {
  4120.     nbytes = DIR_BUF;
  4121.     }
  4122.  
  4123.     bytesStored = 0;
  4124.     while (bytesStored==0) {
  4125.     bytesRead = Fs_GetdirInt(fd, nbytes, kBuf, &offset);
  4126.     bytesUsed = 0;
  4127.     if (debugFsStubs) {
  4128.         printf("Fs_Getdirentries got %d bytes from Fs_GetdirInt\n",
  4129.             bytesRead);
  4130.     }
  4131.     if (bytesRead <=0) {
  4132.         return bytesRead;
  4133.     }
  4134.  
  4135.     /*
  4136.      * Scan through the entries converting them to the new format.
  4137.      * directPtr points to the directory we read in.
  4138.      * directPtr2 points to the directory we are creating.
  4139.      * We can take bytesRead bytes from directPtr, and we count these
  4140.      * in bytesUsed.
  4141.      * We can put nbytes bytes into directPtr2, and we count these
  4142.      * in bytesStored.
  4143.      */
  4144.  
  4145.     directPtr = kBuf;
  4146.     directPtr2 = kBuf2;
  4147.  
  4148.     while (bytesUsed+sizeof(u_long)+2*sizeof(u_short) <= bytesRead &&
  4149.         bytesStored < nbytes) {
  4150.         dirsiz = DIRSIZ((struct direct *)directPtr);
  4151.         if (dirsiz > sizeof(struct direct) || ((struct direct *)
  4152.             directPtr)->d_reclen > FSLCL_DIR_BLOCK_SIZE) {
  4153.         printf("Fs_Getdirentries: Directory record too long!\n");
  4154.         Mach_SetErrno(EINVAL);
  4155.         return -1;
  4156.         }
  4157.         if (((struct direct *)directPtr)->d_ino != 0) {
  4158.         if (bytesUsed+dirsiz>bytesRead || bytesStored+dirsiz>nbytes){
  4159.             break;
  4160.         }
  4161.         bcopy(directPtr, directPtr2, dirsiz);
  4162.         ((struct direct *)directPtr2)->d_reclen = dirsiz;
  4163.         bytesStored += dirsiz;
  4164.         directPtr2 += dirsiz;
  4165.         }
  4166.         bytesUsed += ((struct direct *)directPtr)->d_reclen;
  4167.         directPtr += ((struct direct *)directPtr)->d_reclen;
  4168.         if (bytesStored > nbytes) {
  4169.         printf("Overflow! %d vs %d, %d vs %d\n", bytesUsed, bytesRead,
  4170.             bytesStored, nbytes);
  4171.         Mach_SetErrno(EINVAL);
  4172.         return -1;
  4173.         }
  4174.     }
  4175.  
  4176.     /*
  4177.      * Set the file pointer.
  4178.      */
  4179.     if (bytesUsed != bytesRead) {
  4180.         status = Fs_LseekStub(fd, offset+bytesUsed, L_SET);
  4181.         if (status < 0) {
  4182.         printf("Lseek to %d failed in getdents!\n", offset+bytesUsed);
  4183.         return -1;
  4184.         }
  4185.     }
  4186.     }
  4187.  
  4188.     /*
  4189.      * Copy out the results.
  4190.      */
  4191.  
  4192.     status = Vm_CopyOut(sizeof(long), (Address)&offset, (Address)basep);
  4193.     if (status != SUCCESS) {
  4194.     Mach_SetErrno(EFAULT);
  4195.     return -1;
  4196.     }
  4197.     status = Vm_CopyOut(bytesStored, kBuf2, buf);
  4198.     if (status != SUCCESS) {
  4199.     Mach_SetErrno(EFAULT);
  4200.     return -1;
  4201.     }
  4202.  
  4203.     return bytesStored;
  4204. }
  4205.